<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>C++设计模式 | whoway</title>
    <meta name="description" content="Personal Blog Website">
    <link rel="icon" href="/images/photo.jpg">
  <link rel="manifest" href="/images/photo.jpg">
  <link rel="apple-touch-icon" href="/images/photo.jpg">
  <meta http-quiv="pragma" cotent="no-cache">
  <meta http-quiv="pragma" cotent="no-cache,must-revalidate">
  <meta http-quiv="expires" cotent="0">
    
    <link rel="preload" href="/assets/css/0.styles.0dbae9ec.css" as="style"><link rel="preload" href="/assets/js/app.c70e21ad.js" as="script"><link rel="preload" href="/assets/js/89.17c69819.js" as="script"><link rel="prefetch" href="/assets/js/10.15222a53.js"><link rel="prefetch" href="/assets/js/100.7e0e5a86.js"><link rel="prefetch" href="/assets/js/101.efd59f25.js"><link rel="prefetch" href="/assets/js/102.dfbdc06c.js"><link rel="prefetch" href="/assets/js/103.d3ab2109.js"><link rel="prefetch" href="/assets/js/104.117957ef.js"><link rel="prefetch" href="/assets/js/105.046e8ff3.js"><link rel="prefetch" href="/assets/js/106.aebdc17d.js"><link rel="prefetch" href="/assets/js/107.248733c2.js"><link rel="prefetch" href="/assets/js/108.a2fecadc.js"><link rel="prefetch" href="/assets/js/109.35196857.js"><link rel="prefetch" href="/assets/js/11.770642f2.js"><link rel="prefetch" href="/assets/js/110.cf3d973c.js"><link rel="prefetch" href="/assets/js/111.f985889a.js"><link rel="prefetch" href="/assets/js/112.ad614f41.js"><link rel="prefetch" href="/assets/js/113.f666653c.js"><link rel="prefetch" href="/assets/js/114.c6c3f384.js"><link rel="prefetch" href="/assets/js/115.e51d3c2f.js"><link rel="prefetch" href="/assets/js/116.4f4b39f5.js"><link rel="prefetch" href="/assets/js/117.99352e11.js"><link rel="prefetch" href="/assets/js/118.c6ae6572.js"><link rel="prefetch" href="/assets/js/119.4ccbe778.js"><link rel="prefetch" href="/assets/js/12.042a92ff.js"><link rel="prefetch" href="/assets/js/120.edda1c4f.js"><link rel="prefetch" href="/assets/js/121.30a638ed.js"><link rel="prefetch" href="/assets/js/122.6efcefb1.js"><link rel="prefetch" href="/assets/js/123.91e6665b.js"><link rel="prefetch" href="/assets/js/124.f27e3d7e.js"><link rel="prefetch" href="/assets/js/125.c75712d5.js"><link rel="prefetch" href="/assets/js/126.ed756cce.js"><link rel="prefetch" href="/assets/js/127.2f06c74c.js"><link rel="prefetch" href="/assets/js/128.d5f6f30e.js"><link rel="prefetch" href="/assets/js/129.508b7eed.js"><link rel="prefetch" href="/assets/js/13.b5280c37.js"><link rel="prefetch" href="/assets/js/130.dc05f9aa.js"><link rel="prefetch" href="/assets/js/131.e0ba69b1.js"><link rel="prefetch" href="/assets/js/132.d79bcaa4.js"><link rel="prefetch" href="/assets/js/133.34acc01a.js"><link rel="prefetch" href="/assets/js/134.dabf64d5.js"><link rel="prefetch" href="/assets/js/135.ad90c915.js"><link rel="prefetch" href="/assets/js/136.dbb0074f.js"><link rel="prefetch" href="/assets/js/137.284ad365.js"><link rel="prefetch" href="/assets/js/138.a4b6856f.js"><link rel="prefetch" href="/assets/js/139.c9c1e20f.js"><link rel="prefetch" href="/assets/js/14.df02ba38.js"><link rel="prefetch" href="/assets/js/140.8b0a9269.js"><link rel="prefetch" href="/assets/js/141.9c7759c5.js"><link rel="prefetch" href="/assets/js/142.a4201a82.js"><link rel="prefetch" href="/assets/js/143.d7da6e8c.js"><link rel="prefetch" href="/assets/js/144.5e48e65d.js"><link rel="prefetch" href="/assets/js/145.a0e2633c.js"><link rel="prefetch" href="/assets/js/146.3c775f9b.js"><link rel="prefetch" href="/assets/js/147.22add89a.js"><link rel="prefetch" href="/assets/js/148.cfde1009.js"><link rel="prefetch" href="/assets/js/149.ffc835b5.js"><link rel="prefetch" href="/assets/js/15.fbdfc4ee.js"><link rel="prefetch" href="/assets/js/150.406c4b20.js"><link rel="prefetch" href="/assets/js/151.b2040eea.js"><link rel="prefetch" href="/assets/js/152.7bc65661.js"><link rel="prefetch" href="/assets/js/153.1d7c65e3.js"><link rel="prefetch" href="/assets/js/154.1309de49.js"><link rel="prefetch" href="/assets/js/155.81d3ee1f.js"><link rel="prefetch" href="/assets/js/156.154a4ef2.js"><link rel="prefetch" href="/assets/js/16.e5eb6147.js"><link rel="prefetch" href="/assets/js/17.57853c4a.js"><link rel="prefetch" href="/assets/js/18.cb9d7518.js"><link rel="prefetch" href="/assets/js/19.f354dc47.js"><link rel="prefetch" href="/assets/js/2.570d8a23.js"><link rel="prefetch" href="/assets/js/20.b5af7fad.js"><link rel="prefetch" href="/assets/js/21.0b1928fe.js"><link rel="prefetch" href="/assets/js/22.f78666de.js"><link rel="prefetch" href="/assets/js/23.29c3f366.js"><link rel="prefetch" href="/assets/js/24.6f596516.js"><link rel="prefetch" href="/assets/js/25.14067b60.js"><link rel="prefetch" href="/assets/js/26.74ba4989.js"><link rel="prefetch" href="/assets/js/27.13d60edd.js"><link rel="prefetch" href="/assets/js/28.9523cb32.js"><link rel="prefetch" href="/assets/js/29.8ec842e9.js"><link rel="prefetch" href="/assets/js/3.3fb3d2e0.js"><link rel="prefetch" href="/assets/js/30.805597a8.js"><link rel="prefetch" href="/assets/js/31.831b195d.js"><link rel="prefetch" href="/assets/js/32.063c672d.js"><link rel="prefetch" href="/assets/js/33.6d93fac3.js"><link rel="prefetch" href="/assets/js/34.56e8263c.js"><link rel="prefetch" href="/assets/js/35.dbe688bb.js"><link rel="prefetch" href="/assets/js/36.dc5af2c1.js"><link rel="prefetch" href="/assets/js/37.0a7494f6.js"><link rel="prefetch" href="/assets/js/38.fe4fc171.js"><link rel="prefetch" href="/assets/js/39.f5ed5e92.js"><link rel="prefetch" href="/assets/js/4.2c405ec8.js"><link rel="prefetch" href="/assets/js/40.fe7e2714.js"><link rel="prefetch" href="/assets/js/41.30b0811d.js"><link rel="prefetch" href="/assets/js/42.76f52d62.js"><link rel="prefetch" href="/assets/js/43.e7bb0817.js"><link rel="prefetch" href="/assets/js/44.ead0e883.js"><link rel="prefetch" href="/assets/js/45.235df046.js"><link rel="prefetch" href="/assets/js/46.5f09e829.js"><link rel="prefetch" href="/assets/js/47.67116354.js"><link rel="prefetch" href="/assets/js/48.31f34543.js"><link rel="prefetch" href="/assets/js/49.10b5ebba.js"><link rel="prefetch" href="/assets/js/5.6f47322c.js"><link rel="prefetch" href="/assets/js/50.c0f0b7f1.js"><link rel="prefetch" href="/assets/js/51.5143f3bf.js"><link rel="prefetch" href="/assets/js/52.eeddfd48.js"><link rel="prefetch" href="/assets/js/53.eb790db5.js"><link rel="prefetch" href="/assets/js/54.8fe5421c.js"><link rel="prefetch" href="/assets/js/55.d8f9004b.js"><link rel="prefetch" href="/assets/js/56.62ac9b92.js"><link rel="prefetch" href="/assets/js/57.a9caec0d.js"><link rel="prefetch" href="/assets/js/58.f93fc522.js"><link rel="prefetch" href="/assets/js/59.a81a03aa.js"><link rel="prefetch" href="/assets/js/6.8c2ea393.js"><link rel="prefetch" href="/assets/js/60.ab782775.js"><link rel="prefetch" href="/assets/js/61.6dd12daf.js"><link rel="prefetch" href="/assets/js/62.76f4b01f.js"><link rel="prefetch" href="/assets/js/63.6f8a4742.js"><link rel="prefetch" href="/assets/js/64.6f8bb1fa.js"><link rel="prefetch" href="/assets/js/65.4120a44b.js"><link rel="prefetch" href="/assets/js/66.360c2d2b.js"><link rel="prefetch" href="/assets/js/67.26f84d32.js"><link rel="prefetch" href="/assets/js/68.68f45e5e.js"><link rel="prefetch" href="/assets/js/69.e311eb56.js"><link rel="prefetch" href="/assets/js/7.6762b2d7.js"><link rel="prefetch" href="/assets/js/70.cea82674.js"><link rel="prefetch" href="/assets/js/71.783ddcf7.js"><link rel="prefetch" href="/assets/js/72.e5467385.js"><link rel="prefetch" href="/assets/js/73.b8fb681b.js"><link rel="prefetch" href="/assets/js/74.1bae37db.js"><link rel="prefetch" href="/assets/js/75.024387e5.js"><link rel="prefetch" href="/assets/js/76.a8e53010.js"><link rel="prefetch" href="/assets/js/77.8c55500a.js"><link rel="prefetch" href="/assets/js/78.7ce90bf5.js"><link rel="prefetch" href="/assets/js/79.ef71713f.js"><link rel="prefetch" href="/assets/js/8.788a6364.js"><link rel="prefetch" href="/assets/js/80.acad589d.js"><link rel="prefetch" href="/assets/js/81.02670d10.js"><link rel="prefetch" href="/assets/js/82.53b7b1ac.js"><link rel="prefetch" href="/assets/js/83.99eb8581.js"><link rel="prefetch" href="/assets/js/84.d1535ce3.js"><link rel="prefetch" href="/assets/js/85.fe2b7de9.js"><link rel="prefetch" href="/assets/js/86.41850272.js"><link rel="prefetch" href="/assets/js/87.1cdc6df9.js"><link rel="prefetch" href="/assets/js/88.01bf3461.js"><link rel="prefetch" href="/assets/js/9.3813842d.js"><link rel="prefetch" href="/assets/js/90.f6ae7e35.js"><link rel="prefetch" href="/assets/js/91.507bc284.js"><link rel="prefetch" href="/assets/js/92.90551782.js"><link rel="prefetch" href="/assets/js/93.dc442d78.js"><link rel="prefetch" href="/assets/js/94.315f4e94.js"><link rel="prefetch" href="/assets/js/95.ccd6c6bf.js"><link rel="prefetch" href="/assets/js/96.0c6d89d0.js"><link rel="prefetch" href="/assets/js/97.1a9f10a9.js"><link rel="prefetch" href="/assets/js/98.43be3caa.js"><link rel="prefetch" href="/assets/js/99.54c8207b.js">
    <link rel="stylesheet" href="/assets/css/0.styles.0dbae9ec.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">whoway</span></a> <div class="links" style="max-width:nullpx;"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">🎓Coding</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/00.Coding/TheBeautyOfProgramming/" class="nav-link">🔖编程之美题解</a></li><li class="dropdown-item"><!----> <a href="/00.Coding/CodeWarehouse/" class="nav-link">🔖代码意识流</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">🚀语言</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/01.Language/Overview/" class="nav-link">🔖概述</a></li><li class="dropdown-item"><!----> <a href="/01.Language/C/" class="nav-link">⭐️C</a></li><li class="dropdown-item"><!----> <a href="/01.Language/Cpp/" class="nav-link">🚀C++</a></li><li class="dropdown-item"><!----> <a href="/01.Language/Java/" class="nav-link">☕️Java</a></li><li class="dropdown-item"><!----> <a href="/01.Language/Python/" class="nav-link">🧩Python3</a></li></ul></div></div><div class="nav-item"><a href="/02.Hardware/" class="nav-link">✔️硬件基础</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">⭐️软件基础</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/03.Software/01.DataStructureAndAlgorithm/" class="nav-link">🐾数据结构和算法</a></li><li class="dropdown-item"><!----> <a href="/03.Software/02.OS/" class="nav-link">💻操作系统</a></li><li class="dropdown-item"><!----> <a href="/03.Software/03.Net/" class="nav-link">☁️计算机网络</a></li><li class="dropdown-item"><!----> <a href="/03.Software/04.SE/" class="nav-link router-link-active">✅软件工程</a></li></ul></div></div><div class="nav-item"><a href="/04.Database/" class="nav-link">🎨数据库</a></div><div class="nav-item"><a href="/05.Engineer/" class="nav-link">🔖学术/工程</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">⚙️工具</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/06.Tools/01.employment/" class="nav-link">🔖求职</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/02.efficiency/" class="nav-link">🚀效能</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/03.windows/" class="nav-link">⚙️Windows</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/04.design/" class="nav-link">🧩设计</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/05.linux/" class="nav-link">🐉Linux</a></li></ul></div></div><div class="nav-item"><a href="https://github.com/whoway" target="_blank" rel="noopener noreferrer" class="nav-link external">
  GitHub
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <div class="sidebar"><nav class="nav-links"><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">🎓Coding</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/00.Coding/TheBeautyOfProgramming/" class="nav-link">🔖编程之美题解</a></li><li class="dropdown-item"><!----> <a href="/00.Coding/CodeWarehouse/" class="nav-link">🔖代码意识流</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">🚀语言</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/01.Language/Overview/" class="nav-link">🔖概述</a></li><li class="dropdown-item"><!----> <a href="/01.Language/C/" class="nav-link">⭐️C</a></li><li class="dropdown-item"><!----> <a href="/01.Language/Cpp/" class="nav-link">🚀C++</a></li><li class="dropdown-item"><!----> <a href="/01.Language/Java/" class="nav-link">☕️Java</a></li><li class="dropdown-item"><!----> <a href="/01.Language/Python/" class="nav-link">🧩Python3</a></li></ul></div></div><div class="nav-item"><a href="/02.Hardware/" class="nav-link">✔️硬件基础</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">⭐️软件基础</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/03.Software/01.DataStructureAndAlgorithm/" class="nav-link">🐾数据结构和算法</a></li><li class="dropdown-item"><!----> <a href="/03.Software/02.OS/" class="nav-link">💻操作系统</a></li><li class="dropdown-item"><!----> <a href="/03.Software/03.Net/" class="nav-link">☁️计算机网络</a></li><li class="dropdown-item"><!----> <a href="/03.Software/04.SE/" class="nav-link router-link-active">✅软件工程</a></li></ul></div></div><div class="nav-item"><a href="/04.Database/" class="nav-link">🎨数据库</a></div><div class="nav-item"><a href="/05.Engineer/" class="nav-link">🔖学术/工程</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title">⚙️工具</span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/06.Tools/01.employment/" class="nav-link">🔖求职</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/02.efficiency/" class="nav-link">🚀效能</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/03.windows/" class="nav-link">⚙️Windows</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/04.design/" class="nav-link">🧩设计</a></li><li class="dropdown-item"><!----> <a href="/06.Tools/05.linux/" class="nav-link">🐉Linux</a></li></ul></div></div><div class="nav-item"><a href="https://github.com/whoway" target="_blank" rel="noopener noreferrer" class="nav-link external">
  GitHub
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <!----></nav>  <ul class="sidebar-links"><li><div class="sidebar-group first"><p class="sidebar-heading open"><span>C++设计模式</span> <!----></p> <ul class="sidebar-group-items"><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#目录" class="sidebar-link">目录</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_01-设计模式简介" class="sidebar-link">01.设计模式简介</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_1-1-课程目标" class="sidebar-link">1.1.课程目标</a></li><li class="sidebar-sub-header"><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_1-2-什么是设计模式" class="sidebar-link">1.2.什么是设计模式</a></li><li class="sidebar-sub-header"><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_1-3-课程用书" class="sidebar-link">1.3.课程用书</a></li><li class="sidebar-sub-header"><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#职业规划" class="sidebar-link">职业规划</a></li><li class="sidebar-sub-header"><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_11分45" class="sidebar-link">11分45</a></li><li class="sidebar-sub-header"><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#shape1-h" class="sidebar-link">Shape1.h</a></li></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_02-面向对象设计原则" class="sidebar-link">02.面向对象设计原则</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_2-5-将设计原则提升为设计经验" class="sidebar-link">2.5.将设计原则提升为设计经验</a></li></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_03-模板方法" class="sidebar-link">03.模板方法</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_04-策略模式" class="sidebar-link">04.策略模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_05-观察者模式" class="sidebar-link">05.观察者模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_06-装饰模式" class="sidebar-link">06.装饰模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_07-桥模式" class="sidebar-link">07.桥模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_08-工厂方法" class="sidebar-link">08.工厂方法</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_09-抽象工厂" class="sidebar-link">09.抽象工厂</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_10-原型模式" class="sidebar-link">10.原型模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_11-构建器" class="sidebar-link">11.构建器</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_12-单件模式" class="sidebar-link">12.单件模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_13-享元模式" class="sidebar-link">13.享元模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_14-门面模式" class="sidebar-link">14.门面模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_15-代理模式" class="sidebar-link">15.代理模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_16-适配器" class="sidebar-link">16.适配器</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_17-中介者" class="sidebar-link">17.中介者</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_18-状态模式" class="sidebar-link">18.状态模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_19-备忘录" class="sidebar-link">19.备忘录</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_20-组合模式" class="sidebar-link">20.组合模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_21-迭代器" class="sidebar-link">21.迭代器</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_22-职责链" class="sidebar-link">22.职责链</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_23-命令模式" class="sidebar-link">23.命令模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_24-访问器" class="sidebar-link">24.访问器</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_25-解析器" class="sidebar-link">25.解析器</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_26-设计模式总结" class="sidebar-link">26.设计模式总结</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_26-1-一个目标" class="sidebar-link">26.1.一个目标</a></li><li class="sidebar-sub-header"><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_26-2-两种手段" class="sidebar-link">26.2.两种手段</a></li><li class="sidebar-sub-header"><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_26-3-八大原则" class="sidebar-link">26.3.八大原则</a></li><li class="sidebar-sub-header"><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_26-4-重构技法" class="sidebar-link">26.4.重构技法</a></li><li class="sidebar-sub-header"><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_26-5-从封装变化角度对模式分类" class="sidebar-link">26.5.从封装变化角度对模式分类</a></li><li class="sidebar-sub-header"><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_26-6-c-对象模型" class="sidebar-link">26.6.C++对象模型</a></li><li class="sidebar-sub-header"><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_26-7-什么时候不用模式？" class="sidebar-link">26.7.什么时候不用模式？</a></li><li class="sidebar-sub-header"><a href="/03.Software/04.SE/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/03.%E6%9D%8E%E5%BB%BA%E5%BF%A0%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%AC%94%E8%AE%B0.html#_26-8-设计模式成长之路" class="sidebar-link">26.8.设计模式成长之路</a></li></ul></li></ul></div></li></ul> </div> <div class="page"> <div class="content"><h1 id="c-设计模式"><a href="#c-设计模式" class="header-anchor">#</a> C++设计模式</h1> <ul><li>注意是：『面向对象类的设计模式』</li></ul> <h2 id="目录"><a href="#目录" class="header-anchor">#</a> 目录</h2> <p>[TOC]</p> <h2 id="_01-设计模式简介"><a href="#_01-设计模式简介" class="header-anchor">#</a> 01.设计模式简介</h2> <h3 id="_1-1-课程目标"><a href="#_1-1-课程目标" class="header-anchor">#</a> 1.1.课程目标</h3> <ul><li>理解『软件的』松耦合设计思想</li> <li>掌握面向对象设计原则 『在我们锤炼、打磨设计模式的过程中、 要理解和掌握：背后的1套设计原则』其实，很多时候『设计原则』要比具体的pattern『模式』还要重要，因为它决定你的pattern的应用</li> <li>掌握重构技法改善设计 『大家在使用pattern的时候要有1个具体的方法』我们的方法就是使用『重构』这样的1个方法。</li> <li>掌握GOF 核心设计模式『课程会把我们主要的以23种设计模式为主的主干模式，会讲给大家』</li></ul> <h3 id="_1-2-什么是设计模式"><a href="#_1-2-什么是设计模式" class="header-anchor">#</a> 1.2.什么是设计模式</h3> <p>“每一个模式描述了一个在我们周围<strong>不断重复发生</strong>的问题， 以及该问题的解决方案的核心。这样，你就能一次又一次地使用该方案而不必做重复劳动”。 ——Christopher Alexander</p> <ul><li>这个是1个建筑学家，在谈模式的时候，对模式有1个定义。</li> <li>后来，软件设计领域呢，大家都借助了『模式』这样的1个说法。</li> <li>『一次又一次地使用该方案而不必做重复劳动』，也就是在我们软件中，我们叫『不需要重复发明轮子』</li></ul> <h3 id="_1-3-课程用书"><a href="#_1-3-课程用书" class="header-anchor">#</a> 1.3.课程用书</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210724151729890.png" alt="image-20210724151729890"></p> <ul><li>主标题：设计模式</li> <li>副标题：『可复用』『面向对象』软件的基础————本书的副标题比主标题更重要</li> <li>『可复用』——<strong>设计模式的目标</strong>，很多人在初期学习设计模式的时候，很容易忘记这样的1个目标，就南辕北辙了</li> <li>『面向对象』——是我们1个具体的手法/方法</li></ul> <blockquote><p>注意：</p> <p>我们通常口头说的『设计模式』是指的“面向对象的设计模式”</p> <p>但是今天，软件行业发生了很多的变化，这本书是1994年写的，中文把它翻译是1998年</p> <p>刚读，这本书可能会朦朦胧胧，理解不是那么准确。</p> <p>课程的目标，就是让大家掌握这本书的精髓。</p></blockquote> <ul><li>发展到今天：</li> <li>其实在『模式』领域还有很多别的模式，比如说：<strong>非面向对象设计类的模式</strong>！</li> <li>比如说，在架构的领域，有一些<strong>架构的模式</strong>。</li> <li>在一些数据库的领域，也有一些<strong>数据库领域的设计模式</strong></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210724151759909.png" alt="image-20210724151759909"></p> <p><font style="background:green;">面向对象背后其实隐藏着2个『思维模型』，这是咋们课程中非常重要的一部分</font></p> <ul><li>思维模型：
<ul><li>底层思维</li> <li>抽象思维</li></ul></li> <li>我们开发人员，其实就是打通这2个部分，我们是人类社会生活的各个领域的需求，表达给计算机，让计算机可以理解，可以帮助我们去执行。</li></ul> <blockquote><p>底层思维，某些详解</p> <p>底层思维，能帮助很多朋友，建立一个很好的机器模型，很多C++的高手，刚开始都是从底层思维开始的！！！</p> <p>但是，光有底层思维是不够的『强调』，很多时候，对程序的理解，你会发现伴随着工作经验的增长，你会发现，抽象思维也非常重要，甚至在某种程度上，它要比底层思维更加重要！！！</p> <p>抽象思维：是1个向上的层次。。。</p> <p>『抽象思维的核心是：去帮助我们，能够很好的去管理你的代码复杂度，！！！』</p></blockquote> <ul><li>C++难学的点在于：编译器在编译你的code的时候，在背后进行了很多很多的plamit???工作。</li> <li>运行机制：不同的编程语言，在运行的时候，会加入一定的机制，比如说，exception异常处理，还又，java还有垃圾收集器</li></ul> <h3 id="职业规划"><a href="#职业规划" class="header-anchor">#</a> 职业规划</h3> <ul><li><p>怎样深入理解面向对象？？</p></li> <li><p>『强调：光有抽象思维，而没有底层思维是不够的，如果你不理解底层思维，其实你的C++编码，很有可能代码就写不好，就会出错，甚至写出来性能不好，，所以，我们这2个思维需要并重』</p></li> <li><p>但是对我们『设计模式』这门课，我们更偏重于，抽象思维的理解！！</p></li> <li><p>评判设计好坏的标准：抽象思维</p></li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210724151833892.png" alt="image-20210724151833892"></p> <ul><li><p>关于：上面大师说的这种情况，我觉得，要不就是『软件』和『建筑』不能类比</p></li> <li><p>要不就是，我理解的深度不够它那么高</p></li> <li><p>但是，在软件设计领域，用户，经常有这样一种冲动，就是有这样的一种变更，去冲击你的『软件体系结构』</p></li></ul> <h3 id="_11分45"><a href="#_11分45" class="header-anchor">#</a> <a href="https://www.bilibili.com/video/BV1kW411P7KS?from=search&seid=5366806679514224635" target="_blank" rel="noopener noreferrer">11分45<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>嗯嗯嗯好，大家好。
呃我们开始我们最佳设计模式的第一讲。
呃我是李建中。
那首先呢我们来看一下我们的整个课程目标。
呃第一，我们希望通过学习设计模式呢，大家能够理解软件的一个综合设计的这样一个思想。
呃第二个部分呢，我们希望大家在这个锤炼啊、打磨设计的过程中，设计模式的过程中呢，实际上要理解、掌握背后的一套设计原则。
啊其实很多时候我们说设计原则它要比具体的某一个pattern还要重要，因为它决定你的pattern的一个一个应用。
第三个部分呢，我们希望就是大家要在使用模式的时候，要有一个具体的这样一个方法啊。
啊我们的方法就是使用重构的这样一个方法。
啊最后呢当然就是我们的课程的会把我们主要的啊就以二十三种设计模式为主的这样一个主干的模式呢啊会讲给大家。
好，那首先呢对于还不是那么了解设计模式的朋友呢，我们首先来看一下什么是设计模式。
呃这个呃是一个建筑学家啊，他在呃谈这个模式的时候对模式有一个定义。
后来呢软件设计领域呢大家都借鉴了这样一个模式的这样一个呃说法啊，就我们说每一个模式呢描述了一个在我们周围不断重复发生的问题啊以及该问题的解决方案的核心。
那么大家看，首先是不断重复，对吧？
再有一个是一个解决方案。
就是这样一个一个关键词，那么这样的话我们就能够一次一次地使用这个方案，而不必重复劳动啊也就是你不需要我们软件，还有一个叫不需要重新发明轮子，对吧？
那设计模式有一领域呢有一本非常著名的书，这也是我们这个课程呢推荐给大家的一个教材啊。
呃那么这本书呢主标题叫设计模式啊，副标题呢叫可复用面向对象软件的基础。
很多朋友呢呃看这本书的时候很容易就去抓它的主标题，就呃呃设计模式啊但是呢我在这里要告诉大家，其实它的副标题啊它的副标题更重要啊，这里啊可复用面向对象这里边挑出两个关键词，第一个叫可复用，可复用是设计模式的。
目标。
很多朋友呢在初期学习设计模式的时候呢，很容易忘记这样一个可复用的目标，这样就南辕北辙了啊第二个呢就是面向对象是我们的手法啊，是我们的一个具体的方法啊。
呃那么我们说整个这个呃这本书呢呃他定义了二十三种设计模式，由于呢他是四个人啊四个人，我们说在在这个写的写作啊就是所以我们有一个说法叫杠offer，就是啊四人组四人团的一个一个说法啊。
那么这本书呢呃创立了模式在软件设计中的一个一个地位啊那由于设计模式一出，确定了设计模式的这样一个地位，其实我们呃通常啊大家在口头。
里面去说的这样一个设计模式呢，我们通常指的就是啊面向对象的设计模式。
但是今天软件行业已经发生了很多的变化啊，那么这本书呢也写作的时间是在九四年，中文版翻译过来大概在九八年这个时间。
那么但是这本书描述的东西却是非常经典啊到今天大家如果去到各大图书排行榜去看的话啊，你会发现他还是呃在计算机这个类别里边啊，还是排名往往是非常top十的这样一个榜单里面。
啊。
当然我们开玩笑说，这本书其实又创造另外一个一个出版神话啊，就是很多人买了不怎么读的一个出版神话对吧我相信很多在可能啊观看这个教程的朋友呢可能之前看过这本书，但是有一种一般刚读这本书的时候，你会有一种朦朦胧胧的感觉是吧。
就是不是那么准确理解不是那么准确啊那我们这个课程呢主要就是帮助大家去深入的啊掌握这本书讲的一个精髓。
好，那我们说那当然这个发展到今天啦，其实呃还在模式领域还有很多别的模式啊，比如说就是非面向对象设计类的模式，比如说有在在架构的领域有一些架构模式啊，在一些数据库领域也有一些数据库领域的设计模式啊等等。
嗯那我们这个课呢谈的是面向对象的设计模式，那它很重要一点就是我们要首先从面向对象来谈起啊面对象呢我们呃很多朋友可以谈起来，因为你现在学的编程语言主流的编程语言都是面向对象，对吧？
但是面向对象呢它其实呢背后隐含着两层两个思维模。
不行，这是咱们课程里面非常重要的一个部分啊。
嗯大家来看这幅图啊，我们左边是一个店啊，右边呢是我们一个我我摘的是一个清明上河图啊，就是我们一个人类社会的一个典型的场景啊那中间就是我们程序，那我们程序员在负责是什么在呃打通两个部分啊也就是我们是是希望把人类的这样一个需求社会生活各个领域的需求表达给计算机，让计算机可以理解，可以帮助我们去执行啊。
呃那么这里面牵扯到两个思维模型，第一个思维模型就是我们这里面讲的就是我们作为程序员和计算机之间的一个沟通，这个是所谓的一个底层思维。
最底层思维呢就是呃我们说是一个偏向下的层，我们需要把握机器底层的一些。
呃微观的构造，比如说我们常常谈的语言的构造，对吧？
然后呢编译器在过程中做了什么事情？
大家知道c加加语言难学的部分在哪里啊？
就这个编译器呢在编译你的code的时候呢，在背后做了很多很多的，我们一般叫playing的工作啊。
那这个编译转换是一个很很跌跳啊，很底层的一个事情。
然后呢内存模型，当你的程序运行的时候漏得到这个这个呃运行时啊漏到merry里边，那么这个你的对象的内存模型它扮演着关键的角色。
然后呢呃不同的编编程语言在运行时还会加入一定的机制，比如说我们说exception，henry啊，异常处理啊或者一些现代语言已经，比如说像java或c。
home，它有一些垃圾收集器啊去帮助你做一些内存的管理工作。
这个都是我们说从微观或者从机器层面去来理解这样一个啊呃对象的构造。
然后我们再来看呃右边这幅图啊，这幅图呢讲的是一个抽象思维，呃那左边刚才我们讲的这个底层思维啊可以帮助很多朋友呢能够建立一个啊很好的机器模型。
呃很多c、dr的高手呢刚开始都是从这里开始的，都是从底层思维开始的。
但是呢我要强调的是，其实光有底层思维是不够的啊那在很多时候呢，你的学习啊，你的这样一个对程序的理解，伴随着工作经验的增长，你会发现抽象思维也非常重要，甚至在某种程度上它要比底层思维更加重要。
啊那抽象思维我们来解释一下，就是它是一个向上。
这样的思维层次啊，它需要将我们周围的世界呢抽象成一个程序代码。
那这里边牵扯到我们说第一个呢面向对象这样的一个理解。
第二个部分呢，比如说组件的封装。
第三呢就是我们谈的设计模式。
第四呢也有些架构模式啊这样些抽象思维，核心是帮助我们能够很好的去管理你的代码复杂度啊。
好，那我们接下来看一下，那怎怎么样深入理解面向对象。
当然我们也说也强调啊，就光有抽象思维而没有底层思维是不够的啊如果你不理解底层思维，其实你的很有可能你的c加加programme就就代码就写不好，对吧？
就会出错啊，甚至写出了性能不好啊。
所以我们这两个思维呢需要并重，但是对我。
我们设计模式这门课呢，我们更偏重于抽象思维的理解。
好，那我们来看一下。
面向对象层面呢呃他如果是向下的话，大家前面如果学了我们其他的面向对象的课程的话，就是你会发现ok，你对封装有了一一层理解，对吧？
比如说它包含了这样一个data map和这样一个呃function map，然后里边的啊内存布局啊等等函数指针啊啊、序函数表啊，这些你都可以去理解，对吧？
然后呢继承，我说你去子类和父类的这样一个对象模型，他怎么去继承父类啊？
然后多态啊多态的机制背后的这个序函数啊呃在序函数表指针这个层面发挥什么样一个动态绑定的作用？
这个都是大家去深入理解啊，就是面向对象的内部机制。
呃这个部分都偏重于我们讲的底层思维。
但是光理解了这个部分其实是不够的，就是我们讲的向上，你需要把握这些面向对象的机制所带来的一个抽象的设计意义啊那么理解如何使用这些机制来表达我们的现实的世界啊或者讲就我这里有一句话叫掌握什么是好的面向对象设计，也就是你呃我们强调你用了所谓面向对象的机制，比如你用了封装、用了继承、用了多态，但是呢并不意味着你的设计就是一个面向对象的，或者并不意味着你的设计是好的一个面向的设计，啊而是呃评判这个设计的标准要靠什么？
要靠我们下面讲的抽象思维。
好，谈抽象思维之前呢，我们需要谈一个抽象思维的一个背景，就是我们软件领域的一个复杂性。
那这个呃是在green，the box啊，就是这位很著名的软件界的一个一个大师啊面向对象领域的大师。
他在一本呃很著名的一本书里面啊就面向对象分析与设计的书里面，呃描述了这样一个非常典型的软件领域的一个一个一个情况啊就说呃他讲乱建筑商从来不会给一个盖好一百层楼的去加一个什么样一个地下室，对吧？
但是呢软件领域经常人们有这样一种啊冲动，有这样一种需求的变更去冲击你的软件体系结构。
那么呃软件呃行业的人经常会面临这样的一种变更的挑战，那这种挑战呢会带来对软件带来巨大的一个一个风险啊所以。
呃我们说软件领域的复杂性的一个根本的原因啊，在这里有我们这样一个关键词，我们叫变化啊。
呃这里面有各种各样的变化啊，我相信大家稍微有一些工作经验的朋友应该能够理解到啊，比如说客户需求对吧？
呃经常在变。
我们说在传统软件是按比如说大家知道windows领域，对吧？
按年去release，那后来到应用软件领域大家会按这个这个几个月啊啊季度release。
呃到了呃呃今天很多互联网公司，我们说已经是呃是按按周relations，甚至按ten、redis，根本的原因就是客户需求在在疯狂在快速的推变化啊当然技术平台啊每年都有新的技术平台引进来，对吧？
那么它也会导致我们变化，还有开发团队的变化、市场环境的变化等等这样的一些。
变化会呃会摧毁这种软件的这样一个体系结构的一个设计。
呃那如何解决这种变化的复杂性呢？
我们人们呢人类解决问题有两种思维模型。
呃首先这两种思维模型不是咱们软件领域所独有的啊，实际上是在我们人类解决呃general的、通用的、人类是人类生活中间面临的问题的时候，都会遇到啊这样两种方法。
第一种呢就是分解。
啊人们面对复杂性呢有一个常见的做法，我们叫叫分而治之，对吧？
其实c语言大家学呃大多人一朋友应该学过c语言，或者一些像帕斯卡一些其他的结构语化的语言，我们结构化的这样的语言是以c语言为代表的，那么它解决的问题就是一种分解的思路，就是分而治之，大问题分成小问题，对吧？
啊这个整体流程分成子流程，啊，将复杂的问题分成多个简单的问题，这个做法非常有效，也是人类非常常用的一个做法。
对吧？
我们的比如说这个这个行政机构啊，我们的社会组织流程啊常常都是呃用分解啊但是我需要解释一下、讲一下。
就只有分解在有些时候是不够的。
啊看人们解决更高层次的一些复杂性的时候呢，人们有一种通用的技术，我们叫抽象。
这个抽象就是由于不能掌握全部的复杂对象，我们会选择忽略一些事物的一些非本质的细节，而去处理泛化或者理想化后的对象模式。
啊那么抽象这个词呢可能刚开始大家目前啊对这个东西呢可能理解还。
不够深入啊没关系，我们的课随着我们课程往后推进，大家会对抽象这个关键词理解会越来越深深入。
呃换句话说，我们的设计模式啊这门课程讲到最后呢，我不希望各位同学呢掌握的是一堆的代码的技巧啊其实那个不重要，重要的是你建立它一套思维的方式和模型。
呃或者讲我我抽取一些关键词，其中的第一个关键词我们今天讲的讲课过程中的第一个关键词就是抽象。
啊那么随着课程的推进，大家会对这个抽象这个关键词理解会越来越深入。
啊我们所有设计模式都是围绕这个抽象这个关键词来进行啊各种这样的一些变化。
好，那我们来说了这么多，对吧？
so，me，the cold？
啊我们来看一看代码怎么来表现这两种。
啊一种叫分解，一种叫叫抽象。
呃我们来调出一个代码啊示例，我们来看一下，代码呢我这里面分两个阶段的代码，第一个阶段就是我讲的分分解的这个部分。
啊首先呢我们来看一下，呃我们这个例子呢是一个维码啊，所谓维码就是我们为了表达咱们课程的需求啊，我们把一些代码的一些不是特别呃要紧的东地方呢都删掉了，只留一些关能够表达关键设计的这个部分的代码啊。
呃那我们目前要演示的这样一个任务呢是一个呃画图的一个简单的应用，大家想象一下，一个一个图形工具对吧？
非常简单的一个画图工具。
好，然后我们。
说那设计这样一个画图工具的话，你需要设计一些形状，对吧？
我们现在放在这个ship里面。
那另外一方面我也需要说明一下，就是为了课程的这个展示代码的嗯这个这个速度啊呃和便利性呢，我没有太遵循很多c加加的标准的编码规范啊，大家注意，比如说像当然呃我们常见说字段作为实现细节，你是需要写写成private的，对吧？
但是呢如果那样写的话，我们代码会写很长。
嗯所以我们我通常是把这些字段呢都直接啊声明成一个public。
另外呢呃我把很多的类型，其实标准的话大家知道一个类型应该说呃放在一个独立的文件里边，那为了方便这个代码演示呢，我把呃呃几个不同的类型呢会放在同一个文件里面，大家看。
point。
很累啊，这是描述这个图形的点，class类啊，这是描述我们这个线条啊。
呃然后recording，olay。
啊那我们在描述这样一个矩形，我们只是写了简单的构造器啊，呃当然它还可能有一些其他的啊构造或者细构，anny之类的东西，我们在这里面都用不到的话，我们都不去写它。
呃然后呢我们来看一下，我们呃在一个表单，假如我们有一个界面啊，呃可以是一个窗口应用啊，就在这个窗口的上呢，假设我们有一个父类啊大家呃这是一个维码表示啊，你不需要关注这个父类。
是是呃具体有什么样一些api啊，大家只关注我们这个member的设计。
好，mate home里边呢我们有两个字段，part一，pot一、punt二，它主要来表达但我们主要是我们这个画图成。
就是用鼠标来表达，对吧？
因为鼠标那么那么这个这个会留下一些点的轨迹，我们取它就是用p一来p二来表达这些点的轨迹。
然后呢我们针对呢因为我们要画线，对吧？
所以我们这个程序呢是在这个界面上要去画线，然后在界面上要去画这个矩形啊等等啊。
呃那么针对线呢，我就需要有一个数据结构啊，我们做一个▁ve，ct or这样一个line啊然后呢针对矩形呢，我们也需要一个数据结构啊，一个▁ve，ct or的一个request，table的一个这样一个向量。
然后呢我们呃当然me方的构造器呃应该会很复杂，我们就不写了，对吧？
它它并不牵涉我们现在的设计啊。
那呃对鼠标的操作呢？
我们有这么几块，一块呢是就是当鼠标按下的时候，当鼠标抬起来的时候，然后还有一个当你界面被刷新的时候，这几个虚函数都会被呃呃系统调用的。
呃至于怎么调用呢，我们这里并不关心这个问题，我们还是往下走啊，看我们的关键的设计。
那当鼠标按下的时候呢，按摩适当的时候呢，我们记录下第一个点，t一，通过去这个参数上的坐标。
当当鼠标抬起来的时候呢，我们取第二个点啊，p二。
好，然后我们就需要看，当然这个是一些界面元素了，大家也不用关心它具体是怎么实现的。
那么比如说我们有个retive button啊，然后我们去去看呃呃目前用户画的选择是画线。
好，那我们就建立一个线的数据结构，然后把这个线呢不是掰开到这个向量里面。
然后再有一个，我们建了一个rock，ten，go的数据集。
结构，然后我们把这个rock，lango呢，positive，bike这个这个recording，week。
好，然后我们接着呢我们做一个reflect啊，replace之后呢实际上就是系统会调用啊on，pant。
那么呃常常啊大绝大多数的像类似这样的虚函数呢，常常需是需要调用父类的虚函数的啊，但这个跟我们关系也不是特别大，我只是说一下提一下就可以了。
然后我们最关键的来看这里啊，那么on pit，我们知道它会在系统被界面被刷新的时候呢会被调用到，那我们这里面就有相应的代码，比如针对直线这个部分啊，我们呃循环这个向量，然后取它里面的每一个坐标点，对吧？
然后他的这个起始点和中度点，start，▁，x、r、y，对吧？
呃然后and▁x and y。
那么画线线呢？
就要传一些其他的参数，假设我们指定就画红色吧。
啊然后我们调用这样一个系统的graph，▁，x底下的一个装嫩的函数，把它画出来。
呃这是针对直线，然后接着要针对矩形啊那么你同样需要这样去画的方式一点，graft，still，real，tango。
然后最后呢也是啊我这个省略号表示就是这个方法。
其实你光做那个事儿是可能是不够的，你还要做一些其他事情。
但是最关键的我们是说关注啊我们的业务逻辑的这个表现部分，就是针对直线和针对矩形的这个画法的部分。
好，那嗯这是第一种设计方法啊第一种设计方法呢我把它定位成一个叫做分解的设计方法。
呃为什么是分解呢？
待会儿大家再来看啊在这待会儿大家再来理解这个为什么是分解。
然后。
我们先接着往下来看，往下看什么呢？
看我们的另外一种做法，就是抽象的做法啊。
那抽象呢是在另外一个类里面在这这里面啊。
好，那抽象的时候呢，我们做了一个ship的一个嗯这样一个父类啊，这个父类里边我们放了一个job的这样一个虚函数或者讲纯虚函数啊，呃在有些地方叫抽象函数，对吧？
呃这里边有呃我又放了一个虚的虚构函数，空的是吧？
呃需要这个稍稍解释一下。
有些朋友可能对这个为什么这个要写一个虚的虚构函数呢？
啊这个虽然跟咱们设计模式没有太大关系啊，但是它对于c加加的语言的正确性是有保证的，就是你只有写了虚的虚构函数呢。
你的子类以后，通过多态的这个释放的时候呢，你的虚子类的虚虚构函数才会被正确地调用到啊，否则会出现一些错误。
好，那我们接着再来看嗯lan。
对，这个呃是point，不用管啊，point是一个辅助类型。
然后我们主要是来看烂，我们所有的继承其实都推荐大家用public继承啊，对吧？
在c加加里面虽然支持所谓的protect继承，para的继承其实很少用啊对吧很少用。
那么这个我们绝大多数的继承都应该去使用这个public的继承。
然后大家来看这个public继承下来呢，我们构造器不用说了啊，还也也是很容易理解，我们最主要来看这个jordan，就这个虚函数呢，我们说我们在这里去over。
read了。
父类的虚函数，对吧？
那实现了这样一个jordan自己画自己的线条的这样一个任务啊，我们这里有一句话叫实现自己的作啊来负责画自己。
那这里面我们就传的参数是这个graphics啊，教练。
好，然后接着来再来看runtime，apple这个logo，除了构造器之外啊，我们接着接下来就是也是实现着自己的这个做啊，跟line其实是非常类似的一个设计啊，计点结论啊，然后来画它。
好，那么接着呢我再来呃呃看一下我们main home的设计，mate home要改一改对吧？
要怎么改呢？
比如说我这个时候呢就没有必要再去设计这个▁ve，ct or line，▁ve ct or呃rock，tango。
呃我只需要设计一个▁ve，ct or shift加s。
一铺就可以了，它可以应对所有的类型对吧？
呃呃但是这里边有一个小小的语言上的呃这个表达方面的变化。
大家来看这个shape，我用的是一个指针，而之前呢用的是一个来这里都是这里实际上是在谈一些底层思维的东西啊，因为它要保证它正确性，然后去解释一下为什么这里面不用这个呃指针，这里面我们直接存储的是对象是ok的，原因是我们不需要多态性，但是这里呢我们需要多态性。
呃所谓多态性就是我们今后呢可能这个里边呢呃虽然我们放的是指针类呃是shift类型，但是我们将来可能希望它指向比如说它真正塞的是可能是一个烂类型，可能是一个rock、ten、go类型，对吧？
所以就为了既是这样一个多态性，我们需要用这个指针。
如果不用这个指针会导致什么情况啊？
解消后它会导致对象切割，就是你传一个烂，它会把你的烂切割成一个小对象。
啊这个后面我们会有一些地方会专门的再去把这个呃呃和咱们设计模式和面向对象设计表达特别相关的语言机制呢，会再帮大家简单梳理一下啊。
但是到目前为止啊，大家首先先理解这里面是不能放一个一个ship对象的，必须要放ship这样一个指针才能表达它的多态性。
好，然后我们塞了一个shift、watch。
嗯呃这三大序函数仍然一样的不变，对吧？
前面这个部分也不变。
呃那在这个部分呢目前也没有什么特别大的变化，但是唯一大家需要注意，因为我们放的是指针，所以。
所以呢这里边要去new一个对象。
呃当然呃学过我们前面课程的朋友应该知道啊，这里边是不能塞一个占对象的，对吧？
需要放一个堆对象的指针。
那对对象当然塞进来啊，对内存管理就有需求，什么样的需求呢？
就是在一定时候，在合适的时候，比如在门缝的机构的时候，你需要负责去释放这个shift。
back里边存的一系列的堆对象的指针啊这个呢在咱们设计模式的课程里面呢也需要注意。
为了表达的这个方便性，我对有些需要内存管理上照顾到的东西呢，我在这里面代码是不写的，但是呃我会在某些地方会点出来告诉大家，比如说像这个地方，你你去new了之后，你一定要在一个合适的地方去去负责它。
delete啊。
好，接着呢我们再来看啊shift这个▁，ve，ct or呢？
我针对啊如果是矩形的话，我们就用push，bike，把它塞啊塞一个矩形的一个一个对对象的指针啊。
好，然后接着呢我们在reflect，跟我们前面的做法是一样的。
呃最后一点呢再来看on，pat这里面的on pit，大家看，我们就嗯直接针对ship的所有形状，对吧？
然后取他的这个调用这个journalization，这个调用之后，大家知道这是个什么方法呀？
虚方法，是吧？
来看这里啊，我们当初实现的就是个虚方法，因为它是虚方法，所以这里面调用我们这里有一句话叫做它是一个多态调用，多态调用的意思就是说根据你内部存储的实际类型，对吧？
如果shift，work里面。
那是一个呃比如说这个i等于零的时候，假如存的是一个line，那么就要去找lan的那个呃job去调用，是吧？
line的job在这里啊。
如果呃这个shift这个i是呃比如说一它里面存储的那个对象呢是一个rock table，那就要去找record那个join，就是这里的这个job，对吧？
这就是所谓的多态调用。
那多态调用我们后面一句话叫各负其责，对吧？
就让你负责自己画自己。
呃如果是▁ra ce table的话，你负责画自己。
啊那这样就完成了我们这样一个第二种写法。
其实第二种设计和第一种设计呢，大家目前在思维上啊来简单地回顾一下，对比一下第一种设计和第二种设计的区别在于什么。
呃如果简单的来看啊，其实有些朋友可能会不觉得他们两个之间有特别大的区别，因为你会发现啊这两种做法呢呃都把功能给实现了，对吧？
但是呢我们作为呃程序员一定要去考虑啊两种设计它的它的分别在哪里？
他哪种设计好？
对吧？
那么我抛出这个问题，大家来思考一下，哪种设计更好？
如果静态的来看这样一个设计结构的话，其实你很难分辨出哪种设计。
好，我们下面呢来呃假设一种情况，什么样一种情况呢？
我们来看，我们假设现在有一种变化，这是我们刚才讲的这个大背景啊。
啊假设现在引入一种变化，比如客户需求变化，什么变化呢？
客户需要。
希望实现呢不仅要实现line，实现这个呃这个reaction够客户还实现希望实现比如说圆形的画法啊。
那这个时候呢作为我们的程序员，大家要在这里要怎么做呢？
那要实现圆是不是要在这里啊我们去写这个sql这样一个源，是吧？
然后呢写完这个sql要在这里边啊。
啊我我具体不写他的数据也够了，你要写他的一个点，是吧？
然后再写它半径啊，然后做它构造器啊等等这些事情，是不是？
而需要在这里做一个什么增加啊，要增加一个类啊，sql这样类啊。
具体里边代码不写了，你仿造那个大家就知道它设计应该怎么做，对吧？
然后呢在这里呢你要怎么做呢？
这个地方是不是也要去再写一个▁ve，ct or？
secret。
wait，your。
personal，tensorflow啊second。
language。
这个地方是一个什么改变是吧？
你要拿着原来的代码要去更改它啊。
嗯接着再来看下边这个地方要不要改？
也要改是吧？
你要做一个l四f是吧？
啊我就不写那个具体的东西啊，大家也可以理解这里边啊。
你需要写的东西是对那个sql进行一个push。
back是吧？
就是mv就是前面写等等等等等写完之后啊，我把这里面稍微写一点点东西啊，比如说前面你要做很多的对象。
那这个构造，然后呢博士b可这样一个比如说一个sql的对象啊当然你这个这个对象也是换成一个sql，是吧？
好，然后接着再来看呢，在下面这里要不要改？
这个也要改是吧？
要针对什么？
就是这也是一个改变啊。
啊这就要针对原型了，是吗？
好，那这个这个具体这个原型也要把它弄过来，我们把这写一下啊。
啊我这儿标注一些注释啊，标志注释是待会我们来回顾来用啊。
这也是一个改变，对吧？
好，那我们到这里呢。
嗯把这个换一下sql。
当然其实这里边呢嗯我就具体不写了啊不写这个句子我就假如就传一个sql对象，假如他可以处理。
比如说这个这个当然我们也是pos说系统类库呢这个graphics上是有一个sql的jordan support这样一个方法，对吧？
可以帮助我们去去写他啊啊这个换过来啊，这是第一种做法，对不对啊？
就是第一种做法，如果你要呃客户需求有变更，对吧？
可以去客户需求变化需要增加一个圆形，那么大家要做哪些工作？
要在这儿做一个增加一个sql的类型，然后找着这个嗯main。
form的源代码里边要加一个sql的▁ve、ct，or，然后又要去在这个具体画取点的时候呢，就是创建这个search对象的时候呢，要。
呃push，bike一个sarah office，这也是一个改变。
然后针对这里呢就是on time的时候呢也要针对sql进行去去单独的去画，这也是一个改变。
呃大家有没有发现这么一个很小的需求，我们要在很多地方去更改你的源代码，对吧？
这个就是大家常常加班的原因啊。
啊有没有发现啊就你的需求在剧烈的变动啊，你你不断地在满足应对这种需求。
好，那我们来看一下第二种做法啊在变化中间会呈现一个什么样的一个形态啊。
第二种做法呢一样的，我们也是要去写一个sql这样一个啊累啊，然后让他去public继承ship啊当然这里边呢一样的，就是说这里边要去写各种各样的东西，但是我也是啊，为了。
嗯哎其实其他地方我就不写了，大家可以猜想应该会怎么做。
最关键的一个点我把它写下来，就是说你还是要去override，对吧？
你要去实现自己的做啊。
好，然后在这里面呢去把它改成什么改成johnsle是吧？
然后这个里边呢相应地去传一个sorry，我删了一点啊。
啊把这个request number这边去掉啊，然后这边呢就是放一些这个sql的数据结构就可以了啊。
实现sql的具体照的方法。
好，然后mini film呢怎么做呢？
大家看要这个地方要不要动啊？
不用动对吧？
为什么？
因为sql继承之ship，它是一个shift。
certainly，accomplish，是不是抽象？
唱类，对吧？
是存续积累，所以surface符合这个规范呢没有问题。
然后再看这个地方要不要变化，就目前来讲，其实这个地方还是要做一些变化，它的变化跟我们刚才这里就所做的一个变更是有一点类似的啊。
但是我也需要提前说一下，我们后边用一些工厂设计模式的话，其实这个地方的变化是可以被消除掉的啊但现在我们说啊我们还保留这个东西啊，这里面要有改变，那这里要不要变化啊？
大家看，不用变，对吗？
就是如果他是sara的话，比某一个i值里边它shift，work里面存的是sql没关系，这个sql的这个指针是一个多态指针，它仍然会正确地找到它的做方法。
去调用它。
所以大家有没有看到第二种写法里面有些朋友已经感受到好处了，是吗？
什么好处呢？
就是这里不用变改变是吧这里不用改变嗯是这里不用改变，只有一个地方有需要做一点点变化，就是这个地方。
但是我们也说过了，如果后面用了工厂设计模式的话，这个地方其实也不用做变化啊，只有一个地方啊。
ship这里面是需要增加的，对吧？
需要增加一个类型，一般来讲是需要你在项目里面添加一个文件，对吧？
呃好处感受到了吗？
大家？
就是第二种设计方法，他由于需求的变更，他的改变很少啊或者或者。
用我们软件另外一种术语叫做它的重用性得到了很高的提升，对吧？
比如这个是可以不断复用的，然后这个呢也是可以不断被复用的。
而第一种写法呢它的复用性非常差，就是当需求变化的时候，你就在忙不停的在在改东西，对吧？
就是这这改一点，那儿改一点啊当然我们这是我们模拟的一个小的例子，大家想象一下，如果放到一个非常大型的工程里边啊，如果你采用第一种设计方法，呃因为你对就拿一个图形应用来说，你肯定不只是画一画对吧？
你还有很多很多的动作操作。
那如果都按第一种设计方法的话，你有你有这样的一个需求变更的话，那么你就要是吧忙。
那呃呃呃翻来覆去了啊，但是第二种设计方法啊他在他第二种设计方案就因为我们强调它也不是说一点都不改变啊，它是要改一点东西的，但是他改的地方毕竟变得比第一种方法要好少很多很多，对吧？
很多地方是不需要改的。
这个就是咱们啊这里边讲的，大家看软回到我们这一句话里边啊，就软件设计的目标啊，我们可以把这个关键词放得非常大，就是希望大家要一定要深刻的通过这个例子来理解我们设计模式主要在讲什么呢就在讲复用性啊，就是所有。
我们设定是模式的目标都是一个复用性，换句话说，我们评判什么是好的软件设计，软件设计的金科滤玉律就是复用性。
你有极高的复用性，你的软件设计才是好的设计。
那么我们再回来看看刚才两种做法，其实第一种做法就是分解大家脑子里面回想一下，第一种做法就是分解，一种分而治之的做法。
第二种做法是抽象是把它们归到一个抽象体系里边，统一的来处理。
回到代码来，再再再看一下啊，再解释一下，到底啥叫呃分解，啥叫抽象啊？
好，这个就是分解，大家有没有看到哎各种各样的这种类型对吧？
分。
蝶式设计啊然后呢在具体操作他们的处理他们的时候，就是分而治之。
大家看这一行，line这行rock，tango，这行surprise，这就是分而治之的做法。
再往下来，这里也是分而治之，对吧？
针对你怎么样啊？
针对我怎么样，针对他怎么样啊这就是分而治之。
然后再再来看这里循环啊，是不是分而治之？
针对直线怎么做？
针对矩形怎么做？
针对原型怎么做？
是不是又是分而治之？
分而治之的做法是非常不容易啊复用的，因为分而治之就是说将来如果有新的这样一种情况的话，你就要针对他再去做一种是要要处理，对吧？
但是呃抽象呢。
抽象就是我们通过一种方法啊呃统一的来处理，什么方法呢？
就是大家来看这个ship，就是就这呃怎么为什么叫抽象类？
就是打这儿来的是吧？
ship是一个抽象类，它表达了一种抽象的一种方式，然后所有类其他的图形类都继承着他就是符合我这个抽象。
那么在其他的地方处理的时候呢就不用分而治之了。
大家看，这就是统一的处理啊简单来说，通抽象能够使得我们用一种通用的方法。
统一处理这里是统一处理，这里我我我我前面说过，如果我们后面用了工厂设计模式的话，其实也可以嗯啊统一处理，然后这里呢也是在统一处理，对吧？
统一处理得到好处是什么？
就是你以后再有任何的变。
变化，我这个处理方法是不变的，所谓不变就是在重用啊就是在复用。
好啊，现在大家我相信各位应该可以把分解这样一个思想和抽象这样一个思想和咱们这个呃代码已经对应起来了，对吧？
就是设计模式啊一是要具备理念，对吧具备思想，但是呢光有思想、光有理念啊还不够，对吧？
你需要对应到你的代码设计上。
呃那谈到这里，我相信有些朋友应该呃有一种心领神会，就是说你问一问自己，是不是以前写代码很容易用一种分解的思想去写代码啊？
那么我们今天没有具体讲某一个模式，呃原因是。
大家必须深刻地去理解啊抽象的这样一种设计方法和设计目标。
然后呢我们后面的课程呢就会带大家啊用利用这样一种抽象设计思想，来针对不同领域的不同问题啊提出不同的模式来去解决它。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br><span class="line-number">177</span><br><span class="line-number">178</span><br><span class="line-number">179</span><br><span class="line-number">180</span><br><span class="line-number">181</span><br><span class="line-number">182</span><br><span class="line-number">183</span><br><span class="line-number">184</span><br><span class="line-number">185</span><br><span class="line-number">186</span><br><span class="line-number">187</span><br><span class="line-number">188</span><br><span class="line-number">189</span><br><span class="line-number">190</span><br><span class="line-number">191</span><br><span class="line-number">192</span><br><span class="line-number">193</span><br><span class="line-number">194</span><br><span class="line-number">195</span><br><span class="line-number">196</span><br><span class="line-number">197</span><br><span class="line-number">198</span><br><span class="line-number">199</span><br><span class="line-number">200</span><br><span class="line-number">201</span><br><span class="line-number">202</span><br><span class="line-number">203</span><br><span class="line-number">204</span><br><span class="line-number">205</span><br><span class="line-number">206</span><br><span class="line-number">207</span><br><span class="line-number">208</span><br><span class="line-number">209</span><br><span class="line-number">210</span><br><span class="line-number">211</span><br><span class="line-number">212</span><br><span class="line-number">213</span><br><span class="line-number">214</span><br><span class="line-number">215</span><br><span class="line-number">216</span><br><span class="line-number">217</span><br><span class="line-number">218</span><br><span class="line-number">219</span><br><span class="line-number">220</span><br><span class="line-number">221</span><br><span class="line-number">222</span><br><span class="line-number">223</span><br><span class="line-number">224</span><br><span class="line-number">225</span><br><span class="line-number">226</span><br><span class="line-number">227</span><br><span class="line-number">228</span><br><span class="line-number">229</span><br><span class="line-number">230</span><br><span class="line-number">231</span><br><span class="line-number">232</span><br><span class="line-number">233</span><br><span class="line-number">234</span><br><span class="line-number">235</span><br><span class="line-number">236</span><br><span class="line-number">237</span><br><span class="line-number">238</span><br><span class="line-number">239</span><br><span class="line-number">240</span><br><span class="line-number">241</span><br><span class="line-number">242</span><br><span class="line-number">243</span><br><span class="line-number">244</span><br><span class="line-number">245</span><br><span class="line-number">246</span><br><span class="line-number">247</span><br><span class="line-number">248</span><br><span class="line-number">249</span><br><span class="line-number">250</span><br><span class="line-number">251</span><br><span class="line-number">252</span><br><span class="line-number">253</span><br><span class="line-number">254</span><br><span class="line-number">255</span><br><span class="line-number">256</span><br><span class="line-number">257</span><br><span class="line-number">258</span><br><span class="line-number">259</span><br><span class="line-number">260</span><br><span class="line-number">261</span><br><span class="line-number">262</span><br><span class="line-number">263</span><br><span class="line-number">264</span><br><span class="line-number">265</span><br><span class="line-number">266</span><br><span class="line-number">267</span><br><span class="line-number">268</span><br><span class="line-number">269</span><br><span class="line-number">270</span><br><span class="line-number">271</span><br><span class="line-number">272</span><br><span class="line-number">273</span><br><span class="line-number">274</span><br><span class="line-number">275</span><br><span class="line-number">276</span><br><span class="line-number">277</span><br><span class="line-number">278</span><br><span class="line-number">279</span><br><span class="line-number">280</span><br><span class="line-number">281</span><br><span class="line-number">282</span><br><span class="line-number">283</span><br><span class="line-number">284</span><br><span class="line-number">285</span><br><span class="line-number">286</span><br><span class="line-number">287</span><br><span class="line-number">288</span><br><span class="line-number">289</span><br><span class="line-number">290</span><br><span class="line-number">291</span><br><span class="line-number">292</span><br><span class="line-number">293</span><br><span class="line-number">294</span><br><span class="line-number">295</span><br><span class="line-number">296</span><br><span class="line-number">297</span><br><span class="line-number">298</span><br><span class="line-number">299</span><br><span class="line-number">300</span><br><span class="line-number">301</span><br><span class="line-number">302</span><br><span class="line-number">303</span><br><span class="line-number">304</span><br><span class="line-number">305</span><br><span class="line-number">306</span><br><span class="line-number">307</span><br><span class="line-number">308</span><br><span class="line-number">309</span><br><span class="line-number">310</span><br><span class="line-number">311</span><br><span class="line-number">312</span><br><span class="line-number">313</span><br><span class="line-number">314</span><br><span class="line-number">315</span><br><span class="line-number">316</span><br><span class="line-number">317</span><br><span class="line-number">318</span><br><span class="line-number">319</span><br><span class="line-number">320</span><br><span class="line-number">321</span><br><span class="line-number">322</span><br><span class="line-number">323</span><br><span class="line-number">324</span><br><span class="line-number">325</span><br><span class="line-number">326</span><br><span class="line-number">327</span><br><span class="line-number">328</span><br><span class="line-number">329</span><br><span class="line-number">330</span><br><span class="line-number">331</span><br><span class="line-number">332</span><br><span class="line-number">333</span><br><span class="line-number">334</span><br><span class="line-number">335</span><br><span class="line-number">336</span><br><span class="line-number">337</span><br><span class="line-number">338</span><br><span class="line-number">339</span><br><span class="line-number">340</span><br><span class="line-number">341</span><br><span class="line-number">342</span><br><span class="line-number">343</span><br><span class="line-number">344</span><br><span class="line-number">345</span><br><span class="line-number">346</span><br><span class="line-number">347</span><br><span class="line-number">348</span><br><span class="line-number">349</span><br></div></div><h3 id="shape1-h"><a href="#shape1-h" class="header-anchor">#</a> Shape1.h</h3> <div class="language-h line-numbers-mode"><pre class="language-text"><code>//Shape1.h
class Point{
public:
	int x;
	int y;
};

class Line{
public:
	Point start;
    Point end;

	Line(const Point&amp; start, const Point&amp; end){
        this-&gt;start = start;
        this-&gt;end = end;
    }

};

class Rect{
public:
	Point leftUp;
    int width;
	int height;

	Rect(const Point&amp; leftUp, int width, int height){
        this-&gt;leftUp = leftUp;
        this-&gt;width = width;
		this-&gt;height = height;
    }

};

//增加
class Circle{


};
 
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br></div></div><h2 id="_02-面向对象设计原则"><a href="#_02-面向对象设计原则" class="header-anchor">#</a> 02.面向对象设计原则</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>好，大家好，那我们开始我们cdr 设计模式的第二讲。
啊，面向对象设计原则。
那有了前面的这个经验呢，首先我们说啊。
变化啊是咱们整个设计里面最大的一个挑战啊。我这里面有一句话叫变化，是复用的天地啊，那面向对象设计或者是。
使用了抽象原则的面向对象，设计的最大优势在于呢我们这有一句话叫抵御变化。当然我们不是说呃有了变化完全完全。
嗯，避免对吧？完全不做任何的改变，就可以应对新的变化。不是这样的，而是说能够将变化的什么范围降到最小。
啊，我们这里面有几句话，首先来看一下。
重新认识面向对象，就是大家在之前在面向对象的理解是封装继承多态是吧？那个是他的什么底层思维层面的理解。
我们再来看看从抽象思维层面来理解。
面向对象，首先它是能够隔离变化，对吧？从宏观层面面向对象的构建方式，更能适应软件的变化，能将变化所带来的影响减为最小。
大家可以回顾一下我们前面的例子里面啊，上节课讲例子里面这个。
使用了shape 这样一个抽象之后呢，啊咱们很多地方都维持一个稳定性和复用，对吧？就不需要再变化了。也就是我们这里讲的这句话。
将变化带来的影响减为最小。第二个呢，微观层面啊就是各司其职。我们微观层面的面向对象的方式，更强调各个类的责任。
啊，由于需求变化导致的新增类型啊，他不会影响原来类型的实现。所谓各负其责啊，我们也。
是回回到咱们上节课的代码来看一下啊这个这个责任的意思啊。
就是。
那责任是大家以后要思考类设计的时候，一个非常重要的一个一个观点。啊，比如说我们以前呢。
这个地方。
大家看没form。
划线的责任是交给了谁呀，交给自己对吧？自己在划线啊，当矩形的话，矩形呢也是责任交给自己，这是第一个版本啊，分解的思路就是自己来去。
做这个画的工作了。但我们再来看第二个版本。
第二个版本不是这样子的，贷款百分之划线的这个责任呢是属于谁？不属于我们form 的对吧？是属于你这个。
具体你的类型啊，你上面如果是shape 的话，如果是line 的话，你负责你的画自己。如果是reactant 话，你自己负责画自己，这就是所谓的。
各负其责啊。
呃，各负其责呢。
沈阳很大的一个呃这个这个借用了我们c 加加或者使用我们自己家里面的这个多态机制，就是接口一致一样。但是。
实现不一样，对吧？就大家都干这个事儿，都干画这个事儿。但是我的话的方式和他的画的方式不一样啊，所以这里边呢就是一个。
啊，多态的调用，它实现了一个责任的啊这样一个分派啊。
所以微观层面啊更强调各个类的责任。
然后呢，从呃那么从这个角度来再来看面向对象是什么的话，我们就看到了啊那样对象的这个首先从语言实践层面啊对象是封装了这个代码和数据啊。
这是一个底层的思维，但从啊规格的层面呢，我们说对象是一系列被可以被使用的公共接口。呃，从概念层面的对象是某种拥有责任的抽象。
啊，所以这句话啊是我们的一个关键的理解，就是你是拥有一个独立的责任的抽象体。
好，接下来我们再来看啊，根据前面对面向对象的认识来看一看面向对象设计原则。
我们这里要讲八大设计原则啊，这些设计原则呢。
我上节课讲过，其实他比具体某一个模式更重要。我们讲的这些模式里边呢，有些模式呢呃今天可能已经不流行了。
啊，有些模式呢已经被有些语言机制给替代了。有些模式呢甚至你可能忘记了都没有关系啊，不重要是吧，但是什么更重要啊，就是我讲的设计原则。
以模式更重要，因为有了这些设计为呃原则呢，其实你有可能发明自己的模式，你也可以去理解千千万万。
更多的啊未来的一些一些其他领域的一些模式。但是呢呃有些朋友就很容易啊就是把呃一个错误的观点学习设计模式。一个错误观点是把模式当作算法来学习。
啊，这是不对的。大家今后会看到两段代码非常像的模式啊，其实他可能表达的是完全不同的设计模式。
啊，但是有的时候呢两端代码相差千差万别，但是他们可能表达的是同一个模式，原因是什么？
原因就是说评判他们的标准，就是我们这里比较讲的设计原则啊，呃所有的设计模式都是依赖我们这里讲的设计原则推导出来的。
如果他违背了设计原则，那么这个模式就是错误的。啊。比如说有的时候我们设计模式是很tricky 的一个地方的一个代码。比如说有一个代码你只改更改了一点点。
但是呢看起来好像跟那个模式的代码没有差太多啊，其实这个时候已经错误了啊，为什么他错误了？就是你拿这些设计模式，它是一把尺子。
你可以去量衡量你的软件设计品质是不是正确啊。
所以。
我们讲大家学习设计呃设计模式一定不要只看代码的调用。对这这个流程啊，如果有些人只满足于说哎我。
我我特别清楚这个设计模式的代码的这样一个调用的这个这个机制啊，其实呃我讲如果你了解驱函数的啊这个调用机制的话。
二十三种设计模式。你你你很快都可以看得懂，对吧？但是看得懂并不意味着自己去设计的时候可以掌握这样一种设计方法，而是说要回到设计原则上。
好，我们来看第一个设计原则，它叫依赖倒置原则啊，这个括号里面是它的一个英文缩写。
依赖倒置原则讲了一个什么意思呢？讲的是高层模块不应该依赖于低层模块，二者都应该依赖于抽象。注意我这个括号里面有一个关键词。
啊，对于这个关键词稳定啊。
然后不应该依赖低层模块。我这有一个关键词的变化，然后二者都应该依赖于抽象啊。
第二句话讲的是抽象，不应该依赖于实现细节，实现细节应该依赖于抽象。啊，这个话怎么理解呢？
大家我们还是回到我们刚才啊。
刚才这个代码里面。
呃，我们来看一下我们这个代码里边，我们来梳理一下啊呃我们。
好，我们来画一下啊，我们跟上一节课这个映射关系。
啊，我们来画一下我们跟上节课的代码的这个映射关系。我们首先来画一下这个may form。
第一个第一个例子里面没放牧依赖。有谁呢？line 对吧？
啊，还有谁呢？rectangle 是吗？
这个依赖关系，大家看它是不稳定的。因为我们上面的话来讲，main form 是属于咱们的高层模块。而line 和react ngo 是属于咱们的低层模块。
由于低层模块，大家看这有一个关键词叫他是容易变化的啊，而高层模块是相对稳定的。那大家看一个稳定的东西依赖于一个变化的东西是。
是不是稳定人也不稳定了，对吧？就不太好。
那么我我们说应该什么转化成二者都应该依赖于抽象。我们来看一下，我们把它转化成第二种方式。
用蓝色笔画一下。
好，第二种方式里边呢，我们是怎么依赖呢？我们这样做了一个转化na inform 呢。
大家有注意到，我们不再去依赖具体的烂了，我们去依赖了一个sheep，是吗？
啊。
对吧，然后续普这边呢。
又有line。
rectangle. 
等等这样类去依赖于ship。
对吧这个shift 我把它用于圈圈圈起来，就是咱们这里边讲的什么抽象。
那就是咱们这里讲。
然后抽象不应该依赖于实现细节。
比如有些人喜欢写这样的代码，在这个抽象类里面返过来啊，去去去使用子类，所以那个就不对了，那几个又违背这个。
这个原理了对吧？就是抽象不应该依赖实现细节。为什么抽象它应该是稳定的啊，如果你依赖一个实现细节。
这这个时间也是容易变化的。那你就又是变成了一个稳定的依赖变化了，是吧？所以实现细节应该依赖于抽象啊，就是反过来大家看这里边。
最最最关键的地方啊就在于line rectangle 不稳定容易变化，对吧？所以他容易出问题，就箭头指向它就是依赖。
他被依赖啊，那么如果再看这边呢。
这个第二种做法是稳定的对吧？为什么稳定啊？大家看shift 是一个抽象体，抽象是稳定的。然后呢一个稳定的依赖，一个稳定的没关系，对吧？
然后一拉一说再去啊，作为一个不稳定的东西，依赖于一个稳定了。那那你不会影响我ship，对吧？你你只是自己在变化。所以所以我们通过这个方式就实现了一个叫做隔离变化。
怎么样隔离变化？
就是把这个地方大家看我画黑色框这个部分line tango 这个变化被隔离起来了啊，而上面部分呢。
ma may form 和sheep 是相对稳定的，对吧？但是这个这个依赖关系是导致了main form 也变得不稳定了啊。
所以这就是我们的依赖倒置原则。依赖倒置原则是一个非常重要的设计原则，它贯穿于我们几乎所有的设计模式啊。
呃，那我们后面在讲课的过讲每一个具体的模式的过程中呢，会详细的去分析。比如说这个模式在如果你不用模式的话，他在某一点上它就违背了我们讲的依赖倒置原则。
啊，那么这个时候我们需要改变，怎么改呢？就是提出抽象类对吧？大家看依赖抽象，依赖倒置原则是非常依赖这个shape 类型抽象类的提出的。
好，我们接着再来看啊，我们第二个。
第二个这个。
设计原则，我们叫开闭原则。
那开辟开放封闭原则讲的是这样一个道理，就是呃对扩展开放啊，对更改封闭啊。
他讲的是类模块，应该是可扩展，但是不可修改啊。那大家想一想，我我我也举一个例子啊，举一个线，首先举一个现实生活中的例子。
嗯，比如说我们现在有一个需求啊，要做一套桌椅板凳啊。那么假如我们把这个需求。
交给一个木器加工厂啊，那这个目击工厂，比如说针对我们这个需求做了一些工作，对吧？你说啊桌子腿儿啊都给你秀恩弄差不多了。
但是到中间去呢，我们突然发现啊，我们这个大楼呢有一个消防管理的规定，就这个所有的办公家具要达到。比如说。
几级阻燃的一个标准？
好，那我们之前这个需求其实没有表达，要给默契加工厂，对吧？现在呢我们把这个新的需求告诉我们这家工厂。
那我们说呃木匠工厂怎么应对呢？有两种应对做法，第一种做法是什么？
之前做不满足需求对吧？那砍了重做呗，改就改掉呗，是吧，全部把那些呃做好的东西扔掉从。
来一遍重新弄啊，这就是一种。
这是一种改变的做法。我们说不太好，对吧？因为他的浪费程度非常大。
嗯，第二种做法是什么？
嗯，我们叫。
聪明的木器加工厂啊，他不会那么做，他会怎么做呢？他会在上面刷一层防火涂料就可以了，是吧？他之前。
已经做了一些工作。如果你要应对新的需求，他在你的基础之上刷一层防火涂料，这是一种扩展的做法啊，就是我们讲。
模块应该可扩展，但不可修改。
我们同样啊也是来大家回到代码上来看一下啊，我们刚才讲的这个道理是什么意思？
咱们刚才在刚呃这个小的例子里边啊，就第一节课这个例子里面呢其实就应用了这样一个开闭原则。
好，我们来看。
这个就是类模块不断在更改是吧？这就是改变大家记住我这个注释了没？这是在改变，对吧？
大招在命令领域啊，这现在静态语言呃，你一改变就意味着什么？你只要改源代码啊，这是改源代码层面。
就是你需要对这一个类呢进行这块文件进行重新编译，重新测试，重新部署是吧？
这就是改变的代价是非常高的啊。
那这个是增加啊，对吧？那第二种呢，我们再来看第二种。第二种设计方法呢，我们是在这儿增加增加就相当于扩展啊，大家知道这个是增加到另外一个文件里边。
吧。
嗯，然后这边呢我们说绝大多数是比较不需要改的，对吧？比如说这个地方是不需要改变的。
当然这个地方我们说用了工厂也不需要改变，是吧，啊，这个地方也不需要改变。所以第二种设计方法就是实际上是一种扩展。
要方式来应对需求的变化啊。
对吧，这是我们就很重要的一个设计原则啊。
就是当我需求啊变更的时候，我不要想着满街去改，我应该想着我去增加一些东西来应对新的需求变化。
啊，这是人类处理很多问题的一个智慧。在面向对象领域也是如此。
然后我们再来看第三个啊原则叫单一职责原则。我们这里讲一个类，应该仅有一个引起它变化的原因。
呃，变化方向里边隐含着泪的责任。
啊，注意这样一个一个责任的说法啊，是我们呃经常会提到的啊，那么有的时候呢大家会发现一个类你会写的很臃肿。
对吧比如说重构里边对吧？就一个内衣这个多少行多少方法，对吧？你比如你一个类有七八十个方法，这个不正常吧。这个这个从感觉上不正常。
当然这个感觉是来自于什么呢？就是你这个类其实你放太多的成员的话，太多的功能的话，其实就是你里边隐含了多个责任。当你隐含多个责任的时候呢，你就会出毛病。
啊，就是多个责任，把你往不同的方向去拉扯。比如说你有子类的时候，你一会儿这个方向，一会儿那个方向啊，我们后面讲到，比如说桥模式，bridge 模式，对吧？
还有像这个呃decorator 模式啊，都会遇到类的责任的问题啊，泪的责任在通常情况下可能表现不是那么的强烈，你感受。
不是不是特别特别深，但是当遇到一些比较呃特殊的场场合的时候，你会发现累的责任呢是非常重要。如果这个地方思考稍有不慎，你就会碰到一些。
这个坑那单一职责可以帮我们梳理这方面，然后离斯科夫替换原则，他讲的是子类必须能够替换他们的积累。
啊，其实就是is a 的另外一种表达啊，但是继承表达类型抽象就是我如果是你的子类。
呃，你所有需要父类的地方，我子类的对象都可以传过去，都可以使用啊吧也朋友说这不是天经地义的吧。对，这个是应该是天经地义。但是在具体实现的时候，有的一些人就会。
打破这个原则。举例来说，有些尝鲜朋友呢喜欢在一个类子类里边，对吧？你比如说你继承了一个父类，你就啪啪啪啪啪，发现他负了伤的三个方法，你是你指的是不能用了。
所以呢就在子类的三个方案里面，咵咵咵就食物exception 直接扔一场，这个做法就不太对了，对吧？这个做法其实就是违背这个子类能够替换父类原则。
就这就充分证明你这个子类当前不是父类的，不应该是继承这个父类，或者压根就就跟这个父类没关系。
或者是我们后边的方法是跟他是一个组合关系，而不是一个继承关系啊，继承必须是用is a 这样一个离我们叫黎斯科夫替换原则来表达。
好，然后我们再来看呃，第五个原则叫接口隔离原则，就不应该强迫客户程序依赖他们不用的方法。
啊，这这个原则有另外一种说法叫接口应该小而完备。所以小就是说不要把不必要的方法把它public 出去，对吧？你尽量比如说你如果只是子类应用使用的话。
那你就把它protected。如果是本类使用的话，你就把它private 啊。如果真正有必要的情况下把它暴露出去啊，你才做成public。
因为嗯如果你无节制的做成public，就很容易让外部的程序就是指的客户程序啊，我们这里面讲的客户程序通常就是使用它的程序。
这种客户程序呢就会跟他产生依赖，一旦跟你产生依赖，你的接口就就需要保持稳定，对吧？如果你更改了，那对方就也要改变。
所以接口隔离原则主要是讲了这样一个问题。
然后我们再来看第六个原则，我们叫啊。
优先使用对象组合，而不是类继承。
呃，类继承呃，在面向对象的初期，大概就是在八十年代末九十年代初的是这个时候啊，面向对象呢呃这个类继承呢非常的受人推崇。
啊，就是这这个呃，我也不知道什么原因啊，可能我猜想。
有很包括很多人许出血面向对象的时候都特别喜欢继承，就觉得继承才是面向对象的正宗门派。
呃，但是这个感觉呢是错误的。呃，我猜想这种错觉部分的来源于有些人会模拟这样的一个。因为通常我们说子类父类对吧？大家会这样讲。
所以因为我们人类就是这样子子夫妇，对吧？这样一辈一辈传下传递下来的。所以大家通常会觉得哎子类父类就是。
呃，跟我们人类这个繁衍关系好像很像。所以有对这个技巧呢就有一种啊来自于这个层面的一种莫名其妙的好感。
但是呢这个这个类比或者这样一个好感是非常错误的啊，其实继承关系更。
更准确的继承关系，实际上是一种类属关系。比如说。
动对吧？和这个生物之间啊，动物继承子生物啊，然后人类呢又继承自动物啊，是这样一个关系。
啊，这才是治最准确的继承关系。或者我们说汽车继承自交通工具，对吧？s u v 继承自汽车，小轿车继承自汽车。
啊，是这样一个类属关系，所以不是很多类型啊都具有继承的这样一个一个关系的。有的时候我们会错误因此而无用继承。
但这个时候呢，经常会有一种另外一种表达方法，我们叫对象组合是吧？
class a 里边放一个class b 这个b 可以呃可以是一个指针或者是一个对象都可以啊。那么我们说。
呃，原因是继承在某种程度上它破坏了封装性，就是继承呢实际上父类给子类暴露的东西实际上是比较多的，对吧？
啊，或者讲子类父类耦合度过高，而对象组合呢则只要求贝组合的对象具有良好定义的外部接口就可以了。他的偶和度相对是低的。
我们后边也有一些模式啊，就是发现你会发现ag 成是不对的，这个时候把它变成组合，哎，马上这个这个这个整个这个设计关系就理顺了。
啊，这个时候就是往往是误用了继承。
这七个原则我们叫封装变化点，使用封装来创建对象之间的分界层，让设计者可以在分界层的一侧进行修改，而不会对另一侧产生不良的影响。
啊，所以其实就是在大家做设计模式啊，当你设计的这个素养逐步提升的时候，实际上你是应该能够在软件领域能够划分出一些所谓的这种。
啊，分界层啊分界层，那么封装是一种啊。
这个从传统的面向对象的底层思维角度来讲，封装就是啊封装代码和数据，对吧？但是这里也要告诉大家，封装更高层次的理解是封装变化点。
啊，一侧变化，一侧稳定啊，是这是一个。
然后我们再来看第八个设计原则叫针对接口编程，而不是针对实现编程。
呃，这里有几条对吧？第一个不将变量类型生命为某个特定的具体类，而是生命为某个接口。当然这个不能绝对化了，绝对化。你比如说你看累。
个这个面料里面死追啊，vector 啊，你the 都他都是具体类型，我们是要主要是那些业务类型啊，你的你的映射，你的业务类型不要生成具体的。
类，而是声明的接口。
呃，客户程序无需获知对象的具体类型，只需要知道对象所具有的接口是吧？这样的话它会减少系统的各部分的依赖关系。
实现了高内聚和综合。呃，同样的我们也是呃对照的代码来说一下这个原则是吧？其实咱们刚才在就是前面第一个。
例子里面对这个原则也有很充分的一个应用。
比如说。
这里就违背了这个接口原则，对吧？面向接口设计的原则。
因为。
大家看这line and rectangle circle there 就是去依赖具体类型了，对吧？而这个呢。
面向接口的设计，对吧？这个就是放具体的呃放接口，放抽象接口，然后再具体处理的时候呢，只使用这个接口的。
通用的这些方法就可以了啊。
对吧，这就是我们的针对接口编程。其实有些朋友看到针对接口编程，你再回想刚才那个依赖倒置原则，你会发现这两个原则是相辅相成的，对吧？
你违背依赖到语言的，你往往就违背了一针对接口编程的原则。那么反过来你违背了接口编程的原则，针对接口的原因，编程原则你也就违背了依赖倒置原则。
他是从不同角度啊，我们很多设计原则是从不同角度看一个问题的。呃，有些问题就是呃很多原则它是相辅相成的，往往是你违背了其中一个圆的其他几个原则，你也通常会违背啊。
好，那这是我们这八个原则。最后针对面向接口这个原则啊，我们要稍微深入的说一下啊。
呃，我这里有一句话叫做面向接口设计啊，它是产业强盛的标志。
接口标准化啊就是一个产业。呃，我这里不指的是软件产业啊，就是他任何行业大家放放眼望去啊。
这个行业如果能够特别强盛的话，这个行业一定有一个非常强大的一种接口标准化的工作在做。为什么呢？因为接口标准化的核心其实就是分工协作。
啊，软件领域的核心其实就是分工协作啊，大家就通过分工协作，然后才能实现复用性，对吗？那么接口在这个里边就扮演着重要的角色。
呃，我们来呃看看其他领域的智慧啊，呃这也是我在讲课的过程中经常提到的一个部分。就是说大家去理解设计的时候呢，有的时候呢。
有就是理解软件设计中有一句思维里跳出软件去看人类在其他领域的呃智慧。比如说我们上节课讲的分解和抽象。
对吧我们再来看接口啊呃。
比如说秦国为什么能统一六国，当然有些人会说秦始皇当时比较有这个有雄才大略，对吧？手下还有李斯啊，还有这些将军啊，非常厉害啊。
但是呢那是那是政治文化文化层面的一些分析，对吧？我们是做技术的啊，我们做技术的人呢我们。
来从技术的流的角度来看看这个问题怎么去找到答案了。呃，这个不是我杜撰的啊，各位可以去查任何的地方。你其实据史书记载啊。
和考古发现秦国时候的兵器啊，它不论东西南北出土地点啊。
这这就是他都有统一的标准，个间隔弩弩机啊，奴体箭头都是一样的，而其他六国不是其他六国，比如说。
各个国家内部也不是啊，比如韩国当时的韩国啊呃不是今天的韩国，当时的韩国呢？
它的通过一些作战的这个呃记载啊，发现他们经常呢就是说呃比如说东边的长兵器厂和西边的兵器厂。
做出来的这这就叫兵器都不一样，就不一样会带来什么问题啊，大侠，你的训练就不一样，对吧？你的到了战场上，你因为运输，因为物资调配的混乱。
啊，那个键和那个那个这几张我积累就不能搭配，对吧？因为你的接口不是标准的啊，所以你的你的装配，你的存储，你的所有地方都没法标准化。
啊，所以当时秦国在这个上面就快速的胜出了六国就他有一种标接口，针对所有武器，有一些接口标准化的这样一个定义。
啊，呃当然大家知道其实不止武器了，对吧？秦始皇当时啊其实也统一了什么。
呃，度量衡统一的前臂是吧，等等这些啊呃当然具体这个工作不一定是秦始皇本人做的啊，可能是他首先啊这个这个李斯奥美某些大臣做的是吧？
就是呃但是我们要说在这一点上啊，咱们也可以说秦国当时是有着充分的这个我们叫做接面向接口设计的这样一个素养。对。
对。
呃，然后我们再来看第二个部分就是嗯。
毕生的活字印刷啊，这毕昇这个活字印刷成为呃呃我们说啊中国的这个四大发明，对吧？推动了人类的文明的前进。
a 但是这个嗯很多人不知道这个活字印刷，我当年也不知道啊，我是后来学了面向对象设计学设计模式之后呢，某一天。
不经意间跟呃这个就是看跟印刷行业的一些朋友交流，也看了一些资料之后，才发现这里面的奥秘啊，我来给大家画一下。
啊，好，我们来看一下b 生当时是怎么样做这样一个我们叫做所谓的嗯。
活字印刷的我们先看看这活字印刷之前是雕版印刷，对吧？胶版印刷是怎么做的啊？假如我们要印四个字。
设计模式。
那就是要先给工匠师傅一个板子是吧，然后他在这里边刻四个字儿设计模式。
然后假如我们现在有一个新的需求，我们是要刻一个什么，比如模式设计。
好，那这个。
时候是师傅，是不是得再拿一个板子？
再去刻这个模式设计。
大家想想，你如果是这个工匠师傅，你烦不烦，你肯定会郁闷死了，是吧？就是你刚看完设计模式，那过几天有一个客户需求，要是客模式设计。
其实东西都一样，只是换了个顺序而已啊，那么你你得这个整个工作得再做一遍。
那当时毕生呢就发现唉这个问题呢。
其实中间可能是有改进的可能性的，对吧？他怎么改进那个问题啊，他这样。
首先呢拿一个本子。
啊。
好，课上字模。
定义好字模的这个啊宽度啊，间距和这个里边的这个。
呃，这个具体的深度是吧，啊，比如说柯好字母啊，那么然后在。
再让这个师傅呢刻字儿。
啊，在每一个字磨上课的设计。
模式。
就把单独把它抠出来，可对吧？
好，那现在就是说客户要什么？如果你要设计模式，我就把这四个字母这样摆设计模式是吧？如果你要模式设计，我就这样吧。膜。
是设计是吧，大家明白了吗？
这是第二种方式叫做活字印刷，就是这个字儿就倍变火了。第一种呢叫雕版印刷是吧？有些人想呀。
呃，说哎呀，这这个雕板印刷也太笨了吧，还确实太笨了啊。但是人类在这个。
在这个活字印刷之前，这个雕版印刷也日用了几百年上千年了是吧？就有时候你发现人类在这个层面上啊做一点点进步是非常难的。但是反过来你去看你的代码的时候，其实很像雕版印刷啊。
你会发现你也你也你也喝。很长时间没有意识到这个问题，是吧？因为。
这边啊。
那这边其实啊第二种做法其实就是我们讲的松耦合设计。所以大家看看毕生啊，我说毕生其实也是一个松耦合设计大师，是吧？
这他很早的时候就意识到啊这个东西第一种做法叫剪耦合啊，最近你看这些字儿和这版是吧，紧贴在一起没法分离的。
第二种是什么板子和字儿分离了，但是他之间有一个关系，这个关系是靠谁定义呢？靠自模的这个接口来定义的。
啊，这也是一种啊我们讲面向接口的这个设计啊。
好，那我们继续回来啊。
呃，那我们说毕生的这个活字印刷其实也是一种呃面向接口设计啊那。
最后呢我们来看一下啊，当然其实啊我在在再说一下这个面向接口设计，对吧？这我只是举了中国的两个例子，你去其实你去看任何各行各业，你去看汽车制造业。
对汽车制造业之所以今天能够发达到这么乘高高高度的流水优化的这样一个标准，对吧？大家会发现他汽车工业里面的很多接口标准。
都掌握在那些核心公司手里，对吧？比如说飞机制造业是吧？大家知道空客，波音其实就制定了很多标准，他才得以把这个分配到全球。
各个工厂来实现大家的高度的写作。啊，所以面向接口设计啊在是传统行业的一个智慧，然后逐步借鉴到我们软件行业。
过来的。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br><span class="line-number">177</span><br><span class="line-number">178</span><br><span class="line-number">179</span><br><span class="line-number">180</span><br><span class="line-number">181</span><br><span class="line-number">182</span><br><span class="line-number">183</span><br><span class="line-number">184</span><br><span class="line-number">185</span><br><span class="line-number">186</span><br><span class="line-number">187</span><br><span class="line-number">188</span><br><span class="line-number">189</span><br><span class="line-number">190</span><br><span class="line-number">191</span><br><span class="line-number">192</span><br><span class="line-number">193</span><br><span class="line-number">194</span><br><span class="line-number">195</span><br><span class="line-number">196</span><br><span class="line-number">197</span><br><span class="line-number">198</span><br><span class="line-number">199</span><br><span class="line-number">200</span><br><span class="line-number">201</span><br><span class="line-number">202</span><br><span class="line-number">203</span><br><span class="line-number">204</span><br><span class="line-number">205</span><br><span class="line-number">206</span><br><span class="line-number">207</span><br><span class="line-number">208</span><br><span class="line-number">209</span><br><span class="line-number">210</span><br><span class="line-number">211</span><br><span class="line-number">212</span><br><span class="line-number">213</span><br><span class="line-number">214</span><br><span class="line-number">215</span><br><span class="line-number">216</span><br><span class="line-number">217</span><br><span class="line-number">218</span><br><span class="line-number">219</span><br><span class="line-number">220</span><br><span class="line-number">221</span><br><span class="line-number">222</span><br><span class="line-number">223</span><br><span class="line-number">224</span><br><span class="line-number">225</span><br><span class="line-number">226</span><br><span class="line-number">227</span><br><span class="line-number">228</span><br><span class="line-number">229</span><br><span class="line-number">230</span><br><span class="line-number">231</span><br><span class="line-number">232</span><br><span class="line-number">233</span><br><span class="line-number">234</span><br><span class="line-number">235</span><br><span class="line-number">236</span><br><span class="line-number">237</span><br><span class="line-number">238</span><br><span class="line-number">239</span><br><span class="line-number">240</span><br><span class="line-number">241</span><br><span class="line-number">242</span><br><span class="line-number">243</span><br><span class="line-number">244</span><br><span class="line-number">245</span><br><span class="line-number">246</span><br><span class="line-number">247</span><br><span class="line-number">248</span><br><span class="line-number">249</span><br></div></div><h3 id="_2-5-将设计原则提升为设计经验"><a href="#_2-5-将设计原则提升为设计经验" class="header-anchor">#</a> 2.5.将设计原则提升为设计经验</h3> <blockquote><p>33:50</p></blockquote> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210806163101161.png" alt="image-20210806163101161"></p> <p>好，最后一点我们来看一下，就是把我们前面讲的8个<strong>设计原则</strong>啊</p> <p>做一些归纳和提升的话，就变成一些<strong>设计经验</strong>。</p> <p>啊，有三类。</p> <ul><li>第一类设计经验，我们叫设计习语，Design Idioms。
呃，当然设计习语一般指的是呃，与特定编程语言相关的低层的一些模式，技巧啊， 惯用法。
<ul><li>比如说像《effective C++》、《more effective C++》、《exception  C++》、《more exception C++》 这些书籍都属于这个层面的。</li></ul></li> <li>然后设计模式呢，我们主要描述的是“类与相互通信的对象之间的组 织关系，包括它们的角色、职责、协作方式等方面。
<ul><li>那主要解决什么？<strong>变化中的复用性的问题啊</strong>，这是我们的Design Patterns。</li> <li>啊，当然还有一些架构模式，对吧，他描述的是系统级的啊，包括子系统的划分责任啊以及协作关系啊。</li></ul></li></ul> <p>呃，我们今天的课程就就谈到这里啊，那么我们下次课程呢</p> <ul><li>会深入的来，去真正进入到每一个模式。<strong>但是就是我今天讲的啊，那么在在进入某一个具体模式之前，你一定要深入的去领会，这8大设计原则啊</strong>。</li> <li>那么这样的话你才能非常灵活的理解和运用具体某1个模式。</li> <li>好，我们今天就到这里。</li></ul> <h2 id="_03-模板方法"><a href="#_03-模板方法" class="header-anchor">#</a> 03.模板方法</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>嗯嗯好，大家好，那我们开始我们c加设计模式的第三讲啊。
呃我们之前呢其实掌握了这个面向对象设计的一些原则、一些目标之后呢，我们这节课就会进入具体的一个模式。
啊我们这节课呢要深入谈的这个就是time，pad，method，呃一个非常经典啊，也非常具有啊我认为具有示范效应的一个模式。
呃那在具体谈这个模式之前呢，我们先来看一下就是二十三种设计模式的一个整体的分类。
这是g、o、f。
在这本就是我们之前提到这本非常经典的书籍里边啊，他对呃二十三种设计模式有这样的一种分类方法。
第一种呢叫创建性。
那它主要解决对象创建的工作。
啊第二类呢叫结构性，啊，主要是解决什么对象啊在需求变化的时候对对象结构的冲击啊啊所呃提供那些模式。
呃第三种呢是行为型，主要是多个类啊之间的这样一个交互的过程中的一些责任的划分的问题。
呃当然j、y、f。
还有另外一种分类方法是从范围啊的或讲或者讲，其实我觉得更多的是实现手段的部分，就是所分了所谓类模式和对象模式。
呃如果简单来说，类模式更倾向于类和子类的啊这个静态关系，呃对象模式呢更多的是处理对象间的动态关系啊或者讲类模式更偏重于什么继承方案，就啊父类、子类啊对象模式更。
偏重于组合方案，就是呃一个类里面包含了另外一个类的对象或者指针啊。
呃当这种分类方法呢呃实际上是呃流传已久了啊，因为g、o、f，它定义了这样一个标准的分类方法。
但是我在教学的实践过程中呢呃也发现了另外一种分类方法，可能对大家去掌握呃、去打磨自己对设计模式的理解更有帮助。
啊那我分为把它分为这么几类啊，第一类我们叫组建写作类，当这些为什么这样分类，我后边呢再讲到每一个类别的时候，会深入地去谈它。
现在呢大家先呃沟思路过一遍啊，就是组建协作，那主要解决的是他们之间的一个协作问题。
第二类呢我们叫单一职责啊，主要解决了类与类之间的一个责任划分的问题。
第三类呢。
对象创建啊主要解决是啊这个对象的创建过程中的依赖关系。
那么第四类呢主要是解决性能问题啊呃第五类呢是接口隔离，第六类呢状态变化。
还有第七类的这个数据结构啊，一些主主要呈现一个非常典型的数据结构的特征。
呃第八类，行为变化。
第九类，一些领域问题啊。
呃那我首先进入下面呢来看一下，就是我们的一个在学习设计模式过程中啊非常重要的一个方法啊，那就是我们这这边标题里面画画的啊，我讲叫重构啊，就是refrain，train。
重构是一个非常啊非常重要的一个一个方式了啊。
那么首先呢我们说面向对象设计模式，它是好的面。
要设计啊所谓好，什么叫好啊？
就是我们上节课其实已经得出一个结论，就是你能够什么应对变化、提高复用的这样一种设计，我们叫好的面料设计啊。
呃但是我们也需要去强调一下就是现代软件的特征啊，它是一个需求的非常频繁的这种变化。
那么设计模式的要点啊大家在这个掌掌握学习的过程中，就是说它的要点就是寻找变化点，注意啊这个关键词啊，然后在变化点处应用设计模式啊或者讲就是说你把你的变化和稳定的部分分离开啊。
呃没有学习设计模式的时候呢，大家去看代码的时候呢，其实你很容易就是一视同仁啊，所有代码。
就是啊他是在一个一个水平线上。
但是学了设计模式之后呢，其实大家慢慢会培养一种思维方式，就是说你会对软件里边的这个整个模块儿啊，或者是系统啊，或者类之间的一个关系有一个重新的认识。
这个关系的最重要的一个认识就是你会发现他们里边的这个有一些是稳定的，有一些是变化。
啊就这种结构化的划分方式是掌握设计模式、运用设计模式一个非常前提的条件。
那么所以我们这里面有一句话叫什么时候、什么地点应用设计模式比理解设计模式结构代码本身更为重要。
就是我这也是我们上节课提到的啊，就是我们一直非常反对的一种观点，一种对模式一种误解，是说。
哦我理解了这个这个模式的代码是怎么走的啊这个代码流程是怎么走的。
其实这个对设计模式你能够看懂设计模式的代码，其实是仅仅理解到皮毛而已啊要真正掌握设计模式的一个啊核心的东西呢，还是要去把握住它的设计的原则，然后在什么时候、什么地方去使用模式，啊也就是我们刚才讲的在变化的地方去使用模式，这个是设计模式理解和掌握最核心的地方。
啊那么我们强调设计模式呢的应用不宜先入为主啊很多呃初学者第一个阶段啊就是没有模式，就是不会使用设计模式。
第二个阶段呢是说啊一上来就就非常呃有冲动去使用模式啊但是我们说这样的一种方法其实也不好。
很容易产生一些误用啊就是说有些其实是它并不适合用了这个模式，而你却去使用了，对吧？
嗯我们说没有呃在真正的软件设计里面也没有一步到位的设计模式啊，敏捷软件我们非常提倡这个敏捷软件开发的这样一个原则，倡导的一个原则就是reflect，going，to path。
啊就是重构到模式，我们讲课的方式也是不会是说上来就告诉大家哦这个是什么什么模式啊，这个用处其实不是特别大，即便你看懂了它，对吧？
我们更多的时候讲课的方式是说没有使用这个模式的时候，咱们的代码啊，它的设计关系、结构关系是怎么样子的，然后呢我们说它有什么毛病，它违背了我们什么样的设计原则啊然后我们再去使用一个迭代的方式啊去修正它重构的方式去。
修正它。
那修正了之后，我们说诶我们通过修正诶得到了一种好良好的解决方案。
这个呢在某种场合，他碰巧就是这样一个模式啊我们讲课的方式是这样，而且我们在推荐大家在实践中啊，在你的这个工作过程中呃也是使用这样一种重构的方式来一步一步地当模式，除非你在这个领域已经超级有经验，对吧？
你可以说你上来对某种模式有一个很好的把握，但一般来讲，我们说你都需要重构啊的方式来得到。
好，那我们在此也推荐大家读呃两本书啊，这个呃都是非常经典的啊两本书，一一本是马丁福勒对吧写的这个重构啊就是reflecting。
呃然后第二本书呢是这个重构与模式，对吧其呃这个呃就就是我们。
刚才讲的这个这个标题，对吧？
reflect，to，pather。
啊那这两本书在代码的质量和代码的设计上面，其实和我们课程讲的很多的思想和方法是非常类似的。
嗯那谈到重构呢，其实我们会有呃很多的关关键的方法或者讲技巧，那这里边我们列了五种技巧，这五种技巧有些朋友可能对他目前理解还不是那么到位啊，但是呃就像我上节课讲的就是说那些原则是很重要的。
然后接着呢就是这些技法也是非常重要的，你需要理解啊在在具体的编程语言里面，比如在c加加这个语言里边，我们对这些关键词的理解，我也认为它比某一个单纯的模式要重要得多啊因为所有的模。
是都会应用到咱们讲的这些东西。
好，第一个部分就是咱们重构过程中经常做的一个事情，就是说静态来转动态，或者讲静态绑定转动态绑定啊，这是一个非常经常做的事情。
第二种呢是早绑定变成晚绑定。
第三种呢是继承啊，变成组合啊这个其实在我们前面的原则里面也谈过这个啊。
然后第四种呢是编译室依赖转成运行式依赖，呃第五种呢是紧偶合转成松偶合。
当然有朋友如果你你到你到一定程度的话，或者你学完这个设计模式课程之后呢，你再回过来看这五个关键词，你会发现这五个关键词讲的其实是一个事情啊或者他的是从不同角度来看待同一个问题啊。
好，那我们接着再往下来。
呃那我们下面就进入我们这个组建协作模式。
组建为什么我把他们归到啊就是呃呃这样一个组建协作模式呢？
就是现代软件专业化分工之后，一个最重要的一个结果，就是划分出来了两个部分，一个叫框架，一个叫应用，是吧？
这是大家现在写程序的时候，你必然要面面对的问题，就是你一定会去使用某些library啊或者framework，对吧？
我我们把libra和free work虽然他们有一些不同啊，但是我们把归在一类里面，就是我们需要去使用他们来写自己的app，对吧？
operation。
那么这样一个划分它必然中间需要有大量的协作的问题啊。
那所以组建协作模式主要是通过我。
按期绑定，注意这个晚绑定啊，那来实现框架与应用之间的一个松耦合啊对，我们也强调的是一个双呃这个两者之间协作时候常用的几个模式。
那么我们有三个模式啊，computer，method，我们叫模板方法。
第二个，strategy，啊策略模式。
第三个呢，average，在某些呃呃编程语言里面也叫element啊，事件模式。
呃当然我也想强调一下，我当我们在讲这三个模式是组建协作模式的时候呢，我们并不是说其他模式跟组建协作没有任何关系，其实它也有关系，只是说这三个模式啊在这个层面体现的最为强烈，特征表现最为明显。
啊包括我们后面谈到单一职责模式的时候，其实有些其他模式太有职责了。
问题，并不是没有职责上的问题，只是我们有些模式在这个层面体现明显，所以我们把它划分到这一类别里。
好，那我们就进入我们这个tab。
master的模式。
我们首先来看一下这个模式的一个所谓的动机，或者是它发生的时候的一个一个一个一个场景啊。
那么主要讲的是在软件构建过程中啊，我们对某一项任务它常常有稳定的整体操作股价。
注意啊，我在讲的过程我会刮勾选一些关键词，啊这些关键词是需要大家特别注意、特别思考的啊稳定的整体操作结构，但是各个子步骤却有很多改变的需求啊或者由于固有的原因啊，比如说就是你你一个是框架，一个是应用，对吧？
而无法和。
任务的整体结构呢同时实现啊你无法同时时间，你必然要出现一个早、一个晚这样的一个关系。
所以我们这个时候呢就就是说如何在一个确定、稳定操作结构的前提下啊来灵活地应对各个子步骤的一个变化啊这里面也是一个变化，这样一个词或者晚期的呃一个一个实现需求。
好，当然谈这现在都是在在在谈了一些嗯呃呃这个这个原则、说法、场景，对吧？
我们还是要回到代码上。
好，我们来看一下代码里边呢怎么样展现这样一种设计的一个一个一个需求啊。
好，我们同样呢也是先拿一个例子来看一下。
首先呢这个level。
就是程序库开发人员啊。
那么从假设我们这样一个呃需求是，首先程序库开发人员他做了呃这样一个library，它里边呢有完成某一项任务的这个几个步骤，比如说step一、step三、三、五，那它实现了这么三个步骤。
哎然后呢我们作为应用开程序开发人员，我们要实现这样一个任务的话，我们也要做step二，比如说step四这样两个步骤啊。
那做完这两个步骤还没完，我们还要做一个什么事情呢？
就是在这里要去具体的呃是就是把这几个步骤以一种某种流程把它串起来。
呃比如说我们首先假设啊假设我们这个流程是这样啊，就step一先执行一下，然后step二的返回值做一个判断。
然后来调用step三，然后呢针对step四呢我们做一个for循环啊，循环执行四次，然后最后再执行step五啊就是这是我模拟的一个流程了啊。
所以这里边呢应用程序开发人员做的是这么两个步骤，同时加上这样一个程序的整体流程。
这个流程是既要调用到类库开发人员写的东西，step一、step三、step五，同时也要调用到应用程序开发人写的stop二、step四，对吧？
好，大家看明白，这是一个非常非常非常简单的一个一个一个东西啊。
当然还是我讲的，就是我们在这个过程中呢其实呃也没有特别的遵循啊就是c加加的一个编码规范，比如说像这些，其实魅函数和这个类应该是放在不同的文件里边，甚至这些实现都是应该放在cc cpp文件。
那个。
还要有它的单独的头文件，对吧？
那么为了方便我们代码演示的原因，我们就先不遵循那样一些非常严格的一些编码规范啊，但是大家要了解那些是应该你在正式的项目里面应该那么做的。
好，那我们接着来说呢，其实这种做法呢还有另外一种做法啊另外一种做法是什么？
我们来看一下这个第二种做法是library。
开发人员呢对，除了我们说他要做step一、step三、step五，对吧？
啊首先这三个步骤要写下来，但是同时呢他也会把step二和step四呢也写下来，但是他不做实现啊。
呃大家想一下啊，比如说可以回顾一下，你在以前一些程序开发经验里面，是不是接。
经常会有一些呃所谓的这种代码样例，对吧？
比如说windows，对吧？
如果你做windows这个程序开发的话，在在最早写windows程序的朋友应该都遇到过，就是微软会推荐你啊，比如说先呃就是做一个windows的典型应用程序的一个流程啊，就是在c源时代的时候，如果你写windows的话，那么他会给你提供一个样例代码，就类似这样子啊，说你要做哪些哪些步骤哪些步骤那就是你直接调用我的函数就可以了。
就像咱们刚才说的这些step一、step三、step五一样，哪些步骤呢需要你自己写，就像你这个step二、step四这一样。
但是呢我们说那个做法呢其实不太好啊，不好的原因就是这个整体的流程呢其实作为呃这个框架开发。
语言是已经帮我们设定好了，对吧？
他他常常是不需要做更改，而且他常常是稳定的。
啊所以呢我们第二种做法就是说呃在这里呢框架开发人员呢或者讲程序库开发人员，他在这里面他可以完全可以把这个流程写下来啊比如说step一啊，在这个room方法里面啊就是其实这个流程跟刚才咱们在这里面的流程是一样的啊是一样的，只不过是换了一个角色。
由什么由框架开发人员来写啊。
step一，然后判断step二的结果，来调用cf三，然后再做for循环，然后再调用step五。
然后呢注意这里stop二和step四是一个纯虚函数，对吧？
就是因为我们现在框架开发人员没法决定他怎么写，要留给什么。
子类来去重写它。
好，那子类在这里呢，作为英语成绩开发人员，我们就首先继承这个library啊，然后我们去重写这两个方法。
那当重写完之后呢，应用程序开发人员子类的应用程序开发人员呢，它直接就是创建出大家看创建出这个application呃这样一个对象，所以这个指针是这样一个多态指针啊，我说它这多态指针指的是它的生命类型，大家看是个library，但它实际类型是一个application，对吧？
所以他会当他调用虚函数的时候，他就会按照虚函数的动态绑定的规则来去调用，但是这里注意round这个方法，我们在这里调用run的时候呢，ram首先不是虚函数，对吧？
这里注意rom不是虚函数，是一个非虚函数啊。
但是若里边调用的某些函数，像step二。
f四我们知道它是虚函数，所以它会根据虚函数调用规则去找什么子类的，就operation的这个里面的实现来去调用，所以我们这个room方法就会得到一个正确的，对吧？
就一、step一、step三、step五，还是调用time play的，就是这里边level里面实现的。
cf二、四，f四还是这样，application里面实现的，对不对？
嗯好，这个调用机制首先大家了解了，对吧？
然后我们再来解释一下，就是这里边有一个有一些细节啊，稍微解释一下。
第一呢，大家有注意要看到这个，就我们上节课其实提到过这个，对吧？
就是作为你一个鸡肋啊，在cgi里面你写一个鸡肋的话，那么有一条原则是你应该把这个鸡肋里面呃虚构函数写成虚的啊，为什么要写成虚的？
其实呢在这里，你去delete的时候啊啊。
你如果不写成虚，所以他就比如说对这个代码，他就调不调到此类的这个细构函数，就有可能出错。
当然你说有些朋友说我这个子类现在没有吸购函数，但你未来一旦有了吸购函数呢，对吧？
所以我们说你任何一个积累啊在c加加里面任何一个积累你去写的时候，你都要去写它的吸购函数，而且也一定要把这个吸购函数写成虚的啊。
好，这是一些小的细节。
嗯我们最重要的是来对比这两种写法这两种写法，第一种写法大家再回顾一下啊，就是library里面只做这个事情，对吧？
如果我们把这两种写法啊在图里边来表示一下，我现在来用一个图表示一下。
大家回顾我们刚才代码啊，我们有两幅图。
嗯。
嗯那这两幅图呢大家来看一下，就是在这里，第一种呢注意对比啊，第一种我们叫结构化软件设计流程，我梳理一下它里面的关系啊，一、三、五，红色的部分啊红色部分是由什么library开发人员写的，就step一、step三、step五啊二、四是蓝色的部分是由应用程序开发人员写的，对吧？
那么但是大家注意这个栏栏框里边啊，应用程序开发人员其实不只干了二、四两个步骤，他还干了一个事情是什么？
就是我这里面小标小小括号二里边啊写了程序的主流程，这个是什么呢？
就是咱们那个魅函数里面写了什么啊step一，对吧？
然后调那个if，step二，然后扩。
和cf三，然后做一个for循环，对对cf四进行调用。
就是这个这个就是我们叫应用程序的流程。
那么这个里边呢这个做法啊我们再和第二种做法来看，这是第二种做法来做一个对比，第二种做法我们换了一种实现方式，我们是把step一、step三、step五仍然是由library开发人员写的，对吧？
但是注意之前啊由应用程序开发人员写的那个部分啊就是就是程序主流程我们把它拉到上面了，就是放在红框里边了，所以这个部分啊啊对，这个部分啊现在被拉到这个上面，就这个部分其实就是那个ram方法写的，对吧？
ram方法里边调用了step一、step三、step五，但是同时也调用到了。
step二和step四，是吧？
那当然现在英语成绩开发人员是不是就省事儿了？
不需要做那个程序的主流程了，对吧？
只写二、四两个步骤就可以了啊，但是我们要注意这里面的调用关系，大家来看一下，第一种调用关系是这样子的，是吧？
蓝色的调用红色的是吗？
就是你这个程序的主流程反过来去调用它的，对吧？
再再来看第二种调用关系是不是这样？
反过来的，注意虚函数啊这其中调用的是虚函数，轩辕树是向向下调用的调子类的，对吧？
如果我把这个关系再梳理一下啊，大家就看到我们第一种写法是一种早绑定的写法，我为什么说他是早绑定呢？
因为library里边啊大家注意，library一般都是写。
改得早嘛，对吧？
这是天天然的，是不是？
就是你你去写你去写一个程序人程序库肯定比你写得早，对不对？
那你去调用程序或调用程序肯肯定是存在的啊，那么所以它是早，对吧？
library早，然后operation。
one是吧？
一个碗的东西掉一个早的东西，这个就叫早绑定啊，或者这是这是非常c语言非常主流的一种做法，对吧？
就是所有编程语言都都都是很默认这种做法啊。
但是呢在面向对象语言之后呢，有一种我们叫做玩绑定的机制啊，大家看就是library里边呢啊注意libra还是写得早是吧？
operation写得晚，但是呢现在是library反过来去调用operation是吗？
那么这样的话就会产生一个我们叫做玩绑定，就是一个早的东西。
对，我在。
写一下啊，这个是早，对吧？
这个是晚啊，一个早的东西在调用一个晚的东西啊这个叫玩绑定啊。
嗯那有了这样一个早保您和晚点的认识之后呢，我们再来啊回到啊我们这个模式啊这个设计模式的定义里面，我们来看一下就是说g、o、f，对于这个模式有这样的一个定义啊，就是定义一个操作中的算法的股价。
注意我还是勾选关键词啊，稳定这个股价是哪个方法啊大家想一下，这是我们第二种写法啊我们第二种写法里边那个room啊那个股价将一些步骤延迟到子类，注意这个延迟啊。
在咱们这个面向对象术语里边啊，我们。
诶一般提到延迟到子类指的就是什么？
定义一个虚函数，让子类去实现这个虚函数，或者叫让子类去owed重写这个悬殊，这就叫延迟到子类。
那延迟到子类其实就是支持子类来变化，对吧？
也就是我现在定不下来，那或者讲我现在定的东西呃和子类实现的东西是不一样的，所以子类就有了有了变化，有了灵活性，对吧？
那么time，pad method的设计模式使得子类可以不改变这不改变这个词啊这个这个词其实我我我觉得更正面的叫法应该是什么？
复用。
不改变就是复用啊，就是使得子类可以复用一个算法结构，并且同时可以重新定义。
这个重新定义呢就是or red了。
对吧该算法的某些特定步骤，这就是摊派买锁的。
那回到我们的代码，再再来和这个这个定义啊来做一个对照哎和映射关系。
好。
对，照着咱们的这个代码呢，咱们看第一种写法，我们说是没有用他们的master设计模式啊这个呢应用程序开发人员的负担就比较重，是吧？
就是就是这种，是吧？
实际上我这里写的它是一种结构化的设计思维，对吧？
大家注意啊就是虽然有的时候你用了面向对象的语言，但你的设计思维有可能是结构化的。
啊然后我们再来看第二种呢，代码。
就是我们是经过了改良，对吧？
改良之后的版本呢，实际上这个就是time，my so的设计模式。
而为什么叫tab。
message？
这个翻译过来是模板方法，所以模板就是一个样板，对吧？
这个run就是一个样板啊。
那这个这个方法就是我们刚才在这里讲的啊，就是一它就是应用程序的主流程啊第二呢，定义一个算法呃操作中算法的股价，然后呢将一些步骤延迟到子类，那使得子类可以不改变。
就是我们这边讲重用，对吧？
再复用一个算法的结构，就是复用这个东西啊复用这个东西，然后同时支持什么子类的变化，对吧？
子类的变化怎么支持呢？
就在这里，我这里面标出来了吧？
step二是一个。
虚函数啊支持变化。
对对，然后这里面是虚函数，就支持变化。
啊所以大家在瞪大眼睛啊看这这段代码是非常非常嗯值得琢磨啊或者值得深入去理解一段代码。
这段代码非常深刻地揭示了我们绝大多数啊百分之九十五以上的设计模式的最核心的一个一个一个结构的特点，就是稳定中有变化啊别说这个是稳定的，ram方法是稳定的，对吧？
然后这个step三、c二、step二、step四又是变化的。
那当然在c加加语言层面体现出来是稳定的，代码你需要写成什么非虚函数。
而。
要支持变化的，要写成虚函数。
step二当然这个地方写成纯虚函数写成虚函数都可以了啊，都不影响它是step。
呃这个technology，master模式啊当然了这这也是这个模式的入。
呃有有些朋友会说哎这个模式有没有缺点呃或者有没有不适合这个模式适用的地方？
有，这就要你看这个地方，就是我们说我们的假定是这个run是稳定的，对吧？
当有些朋友就会说了哎那李老师这个这个状有可能不稳定啊，我假设一种情况这样一个情况，那么这个状就不稳定了。
当然如果你这个假设合理的话，那这个状就会变得不稳定，对吧？
那么当然这当你去假设这个不稳定的时候，我们说它就不适合用tap led master的模式了啊对吧？
就是他们的method是。
经济模式的一个前提条件就是这个ram必须稳定，也就是说你必须有一个稳定的算法的股价结构可以被重用。
如果你不稳定，那么tab master的模式就不成立了，对吧？
因此呢很多人就哎就喜欢这这样挑战，就是要是假设这个地方不稳定，比如说step一也不稳定啊，其实我们现在step一是稳定的，对吧？
它是个非虚函数，你如果也假设它不稳定，那它就应该也设计成虚函数，对吧？
step r三不稳定，那也应该是应序函数，step五也不稳定，也应该是序函数。
当然有些朋友也会假设就是整个状都不稳定，是吧？
那么如果这么极端的，大家来去推导啊，就是说假设这个不稳定假设那个不稳定假设那个不稳定，对吧那你会得出一个结论，你软件体系结构里边的所有的。
东西都不稳定。
那么这个时候有些朋友问，要是用哪个模式，那我的答案是这个时候任何一个模式都不可以使用，为什么？
就是你所有东西都在变化，对吧？
那么当然这个时候注意，设计模式的假设条件是必须有一个稳定点啊必须有稳定的，如果没有稳定点，设计模式就没有任何作用啊。
那么反过来，有些朋友也会做另外一种极端的探讨，就说诶刘老师，假设这个step二也是稳定的，就是说我不需要子类去实现，我我父类实现一个就是永远子类所有都都可以去复用这个，对吧？
如果step四也是稳定的，那么这个时候要还还要不要这个text？
master模式一模式啊？
当然不要了，就是当你假。
定所有东西都是稳定的时候，设计模式也没有任何意义了。
对啊，设计模式最大的作用就是在变化和稳定中间寻找隔离点，然后来分离他们，从而来管理变化啊。
啊或者用computer这个这个说法是把变化像小兔子一样关到一个笼子里面，让他在那个笼子里面随便跳，而不至于跳出来把你整个房间给污染掉，对吧？
嗯所以一个正常的软件体系结构啊呃一定是有既有变化，又有啊又有这个稳定点。
呃你不可以做两种极端的探讨，一种极端就是所有都是稳定，那设计设计模式没什么可用的，对吧？
第二。
这种呢就是说全都是变化的，那所有的设计模式都从此失效啊所以我们从time和mysql的设计模式，这个这个模式啊可以大家可以得到一个非常重要的一个一个一个启发和思考。
就是说呃在模式应用的时候呢，你的核心就是说你要去分辨出来软件体系结构里边哪些是稳定的，哪些是变化的啊。
好，那有了这样一个认识之后呢，咱们再回来啊回到咱们这个ppt里边，就我想我想再回到这幅图里边啊再回到这幅图里面，大家再想一下，就这个这个东西，程序主流程，对吧？
就是说我为什么要放到这里啊？
就是我们有一个假定，就是它相对稳。
定对我我们说的稳定和变化是有相对性的啊你你在这个世界上其实你很难说有什么什么永远不变的，但如果它比如它的变化速率是是一年一变化，而另外一个地方是一个月一变化，那这个就是相对它是稳定的。
啊所以程序主流程结构啊这个东西，我们的假定在绝大多数场合它都是倾向于稳定的，它比此步骤要容易稳定下来，啊所以它更具有复用价值。
啊当然有的时候啊在某些情况下，我们说这种做法呢就是带来一个弊端带来一个什么样的弊端啊解释一下。
就说大家有时候会发现啊，你在传统啊第一种做法底下结构化软件设计，底下呢你你用这种做法，应用程序开发。
按人经常会被逼的水平变得很高对吧？
为什么你要自己手工去写那个主流程是你抄也得抄一个对吧？
比如说写windows程序的话，如果你用c语言写的话，你经常要抄写一个模板，对吧？
就是那个那个窗口整个创建过程啊。
但是呢在面向对象的时代，如果你用了technology，is的设计模式，而且绝大多数我在这里也要也要说一下，绝大多数的这个软件狂连家里面都有tap，a、master设计模式啊那么这个时候呢你的这个设计呢实际上是被塞到了就是那个应用程序的流程呢核心流程是被塞到了父类里边，所以做硬成员开发人员常常看不到，对吧就是你看不到那些变化过程啊，你只需要有时候你只需要写几个步骤就完了啊甚至就像我们的程序里面，你是就是有的。
说你连魅魅函数那那些东西都不用写，你只要额外的几个虚函数，这个程序就自动地被连接起来，被执行啊所以在在命令那样时代，在time，national这个底下呢，如果你不是写library的开发人员啊，你是写application的开发人员，你经常会面临一种困惑，就是有一种只见树木不见森林的感觉，对吧？
因为你在写那些子步骤，你没有去写过那个核心流程，对吧？
呃但是我们掌握了type master设计模式的朋友应该了解，你要试图去了解如果你是应用程序开发人员的话，你要试图去了解libra里面做了什么。
好，那如果我们对照着这个这个类图的关系啊，就是二十三种设计模焦，f二三设计模式，这本书里面呢其实定义了这样一个一个一个设计结构，那我在这里也也也是要特别的提醒大家啊。
呃。
你当你看这个类图里面呢最重要的部分是看什么啊？
看这个，我用两种颜色来画，首先呢这个呢我把它画成红色的部分啊然后呢下面呢这个呢我把它画成蓝色的部分。
好，什么意思呢？
解释一下，红色的部分就是呃稳定的部分，蓝色的部分呢就是变化的部分。
我希望大家呢在我们后续的课程里边养成这样一个习惯，就你看任何一个设计模式的时候呢，你都包括尤其是他的类图啊，你都去用一个笔去画一画这个类图里边哪些是稳定的，哪些是变化的。
当你形成了这样一种习惯啊呃训练之后呢。
你对模式的理解会更上层楼啊，而不是说只看它的一个代码关系啊。
呃关键就是理解它里边的一个力量的对比啊，就是变化和稳定的力量。
好，那有这个当然对照咱们这个红色的部分，就是在咱咱们代码里边那个ram，对吧？
他们的method，prime table，operation一是咱们里边的那个什么step二是吧？
prime two，operation二就是咱们里面的step四啊。
呃这个counter，class就是那个子类去over ray的父类里边的那个序寒那俩序函数了，是吧？
但他这里面没有去写其他的那些就是step一、step三、step那些函数了。
好，最后我们总结一下，首先呢我们说time，man，so的模式啊，我之所以把它作为第一个模式啊，而不像很多呃很多图书。
报，或者他不是把ten、master作为第一啊我这是呃我我讲课我的时候，我总是把tensorflx作为第一个模式，为什么呢？
第一呢，这个模式呢非常的常用特别的常用啊，像我把这个画笔还是换回这个红红色的部分啊，呃非常常用。
那么在面向对象系统中间啊，几乎我可以这样断定啊，只要你写过所谓的面向对象的应用程序，一定用过tap、ten、master设计模式啊。
有些人不信啊，就哎呀是都都没用过，那是你没有意识到。
如果你意识到认识到这个模式的话，你再去找一找你写过的任何一个呃面向对象某呃这个这个应用程序啊当然你可能不是全貌，所以不是全貌就是说不是说那个父类和子类都是你定义的，有可能是那个父类是别。
认定你的你写你是在那写子类的，对吧？
但是我们说随着大家的这个提升呢，常常你也要去写那个父类啊。
好，那我们说在面向对象系统里面应用极其广泛啊。
呃反过来说，如果如果你一个面向对象系统里面连他们的master设计模式都不用的话，就这个还叫面向对象嘛啊都不一定了哈。
啊第二呢，它的机制非常简洁。
有些人可能听到这里说哎李老师这个这个这个就叫tap，ten，白色的设计模式啊我以前就已经在用了，对吧？
我只是不知道它叫这个名字而已啊。
那没关系，其实今天的这个课程帮助大家重建这个思考过程，最重要的其实就是这幅图，对吧就是这个红色和蓝色你一定要区分开来。
那为什么很多人觉得自己之前已经用过了它的基？
这非常简洁，就是虚函数，对吧？
就是你看得懂虚函数，time，music模式的代码的调用机制你一定是懂的啊，但是呢光能看懂机制是不够的，对吧？
就是我们说这个设计的这个这个偶合关系，你这样理解，它为很多应用程序框架提供了灵活的扩展点啊。
呃这也是一些关键词啊，大家在面对象术语领域只要提起什么叫扩展什么叫扩展？
继承加虚函数，对吧？
继承加多态就是我此类去继承父类，然后对你的虚函数进行or red，这个就叫扩展啊，是代码复用方面的基本实现结构。
那么除了可以灵活的是应对子步骤的变化之外啊，time。
music这个这个模式呢它内含了一种反向的控制结构。
所以这个反向的控制结构是我们有一句话叫做不要调用我不要调用，我让我来调用你我我再来翻到咱们最早那幅图一边啊，大家看这这个话啊，就在time，music设计模式之前呢，软件体系架构的主流是什么是这幅图，就是应用程序开发人员来调用library开发人员写的代码啊。
当time，pleasure的设计模式或者以面向对象为主的设计，这种设计模式变成主流之后呢，这个调用关系反转。
反转是从站在library开发人员的角度来讲啊，就是说你不要调用，让我来调动你，那当然我怎么调用你呢？
我是一个早的东西，你是一个晚的东西，对吧？
我是要通过虚函数的这种玩绑定的机制啊。
来调动。
当然提到这里稍微提一下，虚函数是面向对象里面最核心的玩绑定机制，但是呢任何一个编程语言里面的完播率机制就绝对不只有序函数啊，像在咱们c加加里面，其实这个还有其他的完美绑定机制，比如函数指针，对吧？
函数指针就是像这这当然这个函数指针这个东西在c元时代已经有了，就说c元严格的意义上也是有玩绑定机制的，只是啊用了函数指针而已啊。
但是函数指针这种玩绑定机制呢，在某种场合，它不如虚函数的这个具有很好的抽象性，对吧？
当然了，你如果看到底层结构里面，还这个虚函数背后就是一个函数指针嘛，对吧？
就是虚函数表上挂了一个函数指针啊。
呃那因为我们回到我们的主题啊，就是说这样一个反向控制结构啊，就是面向对。
对象和结构化程序设计非常重要的一个区分就是不要调用我，让我来调用你。
这是站在类库开发人员的这个角度来说的。
好，那在具体实现方面呢讲，有些细节啊稍微说一下。
就被company，master调用的需方法呢可以有实现，也可以没有实现啊，没有实现的话你就是存续方法，对吧？
就像我们的呃一般呢推荐把它们设计成什么protect的方法，是吧？
就受保护方法，为什么呀？
其实就是说就是这个prime at operation一，prime two operation二，为什么要受保护啊？
因为这些方法呢单独作为一个方法呢，它的意义它是不大的，或者是是没有的，对吧？
就是说他作为public方法出去，让人家让外界单独调用它是没有意义，它往往是要放到一个流程里边才有意义。
就是你你的前面，你的后边也有相应的步骤做铺垫，你你调你起来才有意义，所以就是一般不共外借调也因此不把他们声明成public，所以声明成这个prime。
prime team啊。
嗯apollo，target，sorry。
啊。
好，那我们整个这个tab，master的这个模板方法的设计模式呢就谈到这里啊。
呃这个模式很简单，但是需要大家很好地去思考，尤其它里边的这个变化和稳定之间的这样一个力量的关系。
那我们后边越来越复杂的很多模式，其实它离不开一个一个终止点，就是说那个变化点和稳定点的关系把握啊。
好，谢谢各位，我们今天就到这里。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br><span class="line-number">177</span><br><span class="line-number">178</span><br><span class="line-number">179</span><br><span class="line-number">180</span><br><span class="line-number">181</span><br><span class="line-number">182</span><br><span class="line-number">183</span><br><span class="line-number">184</span><br><span class="line-number">185</span><br><span class="line-number">186</span><br><span class="line-number">187</span><br><span class="line-number">188</span><br><span class="line-number">189</span><br><span class="line-number">190</span><br><span class="line-number">191</span><br><span class="line-number">192</span><br><span class="line-number">193</span><br><span class="line-number">194</span><br><span class="line-number">195</span><br><span class="line-number">196</span><br><span class="line-number">197</span><br><span class="line-number">198</span><br><span class="line-number">199</span><br><span class="line-number">200</span><br><span class="line-number">201</span><br><span class="line-number">202</span><br><span class="line-number">203</span><br><span class="line-number">204</span><br><span class="line-number">205</span><br><span class="line-number">206</span><br><span class="line-number">207</span><br><span class="line-number">208</span><br><span class="line-number">209</span><br><span class="line-number">210</span><br><span class="line-number">211</span><br><span class="line-number">212</span><br><span class="line-number">213</span><br><span class="line-number">214</span><br><span class="line-number">215</span><br><span class="line-number">216</span><br><span class="line-number">217</span><br><span class="line-number">218</span><br><span class="line-number">219</span><br><span class="line-number">220</span><br><span class="line-number">221</span><br><span class="line-number">222</span><br><span class="line-number">223</span><br><span class="line-number">224</span><br><span class="line-number">225</span><br><span class="line-number">226</span><br><span class="line-number">227</span><br><span class="line-number">228</span><br><span class="line-number">229</span><br><span class="line-number">230</span><br><span class="line-number">231</span><br><span class="line-number">232</span><br><span class="line-number">233</span><br><span class="line-number">234</span><br><span class="line-number">235</span><br><span class="line-number">236</span><br><span class="line-number">237</span><br><span class="line-number">238</span><br><span class="line-number">239</span><br><span class="line-number">240</span><br><span class="line-number">241</span><br><span class="line-number">242</span><br><span class="line-number">243</span><br><span class="line-number">244</span><br><span class="line-number">245</span><br><span class="line-number">246</span><br><span class="line-number">247</span><br><span class="line-number">248</span><br><span class="line-number">249</span><br><span class="line-number">250</span><br><span class="line-number">251</span><br><span class="line-number">252</span><br><span class="line-number">253</span><br><span class="line-number">254</span><br><span class="line-number">255</span><br><span class="line-number">256</span><br><span class="line-number">257</span><br><span class="line-number">258</span><br><span class="line-number">259</span><br><span class="line-number">260</span><br><span class="line-number">261</span><br><span class="line-number">262</span><br><span class="line-number">263</span><br><span class="line-number">264</span><br><span class="line-number">265</span><br><span class="line-number">266</span><br><span class="line-number">267</span><br><span class="line-number">268</span><br><span class="line-number">269</span><br><span class="line-number">270</span><br><span class="line-number">271</span><br><span class="line-number">272</span><br><span class="line-number">273</span><br><span class="line-number">274</span><br><span class="line-number">275</span><br><span class="line-number">276</span><br><span class="line-number">277</span><br><span class="line-number">278</span><br><span class="line-number">279</span><br><span class="line-number">280</span><br><span class="line-number">281</span><br><span class="line-number">282</span><br><span class="line-number">283</span><br><span class="line-number">284</span><br><span class="line-number">285</span><br><span class="line-number">286</span><br><span class="line-number">287</span><br><span class="line-number">288</span><br><span class="line-number">289</span><br><span class="line-number">290</span><br><span class="line-number">291</span><br><span class="line-number">292</span><br><span class="line-number">293</span><br><span class="line-number">294</span><br><span class="line-number">295</span><br><span class="line-number">296</span><br><span class="line-number">297</span><br><span class="line-number">298</span><br><span class="line-number">299</span><br><span class="line-number">300</span><br><span class="line-number">301</span><br><span class="line-number">302</span><br><span class="line-number">303</span><br><span class="line-number">304</span><br><span class="line-number">305</span><br><span class="line-number">306</span><br><span class="line-number">307</span><br><span class="line-number">308</span><br><span class="line-number">309</span><br><span class="line-number">310</span><br><span class="line-number">311</span><br><span class="line-number">312</span><br><span class="line-number">313</span><br><span class="line-number">314</span><br><span class="line-number">315</span><br><span class="line-number">316</span><br><span class="line-number">317</span><br><span class="line-number">318</span><br><span class="line-number">319</span><br><span class="line-number">320</span><br><span class="line-number">321</span><br><span class="line-number">322</span><br><span class="line-number">323</span><br><span class="line-number">324</span><br><span class="line-number">325</span><br><span class="line-number">326</span><br><span class="line-number">327</span><br><span class="line-number">328</span><br><span class="line-number">329</span><br><span class="line-number">330</span><br><span class="line-number">331</span><br><span class="line-number">332</span><br><span class="line-number">333</span><br></div></div><h2 id="_04-策略模式"><a href="#_04-策略模式" class="header-anchor">#</a> 04.策略模式</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>嗯。
好，那我们开始我们c 家设计模式啊，策略模式啊strategy 的。
讲解。
那首先大家来看一下我们策略模式啊，他仍然是一个组建协作类的模式。
呃，这个模式呢跟我们上节课谈的这个time and method 啊，模板方法模式其实我认为是有着异曲同工之妙啊。
那首先大家来看一下策略模式的一个动机。
呃，他解决的问题是在我们软件构建过程中啊，有些对象使用的算法啊，当然这个算法是一个广义的算法啊，可能多种多样。
那经常改变啊，那么如果将这些算法都编码了这样一个对象中间呢啊。
这可能是也出街的做法啊，就会使得第一使得你这个对象变得非常复杂。而且我们第一第二点就是有时候支持你不使用的算法。
或者不频繁使用的算法，他也是一种性能负担啊。
那么这个问题呢，在我们现实啊中间怎么呃怎么样用某种模式来解决呢？我们还是回到代码来看一段代码。
呃，我们假设一个呃一个场景啊，这个呃是一个税呃税种的计算。比如说我们在很多的这个嗯。
商电子商务系统里面，我们常常需要这个做订单的这样的一个呃计算，对吧？呃，订单计算里面除了你的金额交易等等。
还有一个很重要的是税的计算。
那么嗯假如我们是支持一个呃所谓跨国的这样一个一个结算的话，那么这里你就需要考虑到不同国家的税呃的这个算法的不同。
是吧那比如说中国啊、美国、德国，他这个税法是差相差度非常之大的，是吧？所以你在这个算法的这个实现层面啊就要支持。
啊，呃变化非常不同的这种呃计算税的方法。
呃，大家可以想一下这个问题，然后我们最简单的做法是什么呢？或者大家第一点想到的做法就是说呃就是说我们现在屏幕展示的这样的一个对吧？
你用一个枚举类型啊来支持我啊实现。比如我现在要支持中国、美国、德国这三种国家的税法的计算。
那在这个枚举类型底下呢，那我们有这样的一个。
sales order 啊啊比如说他这个co zr 的内部呢，就会有些地方就牵扯到税法的计算的时候呢，我们就用这样一个。if else. 
或者是switch case 这样开关语句段来做一个判断。比如说这个税如果是中国的税法的时候呢，那么我们就要做按按中国的税法的这样一个嗯。
啊啊，规则来计算啊，如果是美国的话，我们就要按照这个规则来计算。如果是德国就要按这个规则来计算。
在。
在这样的一个做法呢呃初看起来啊没有什么特别不合适的，对吧？大家可以想一下，就是说这个首先只要你算法能够正确的实现呢。
就做吧。
相也无可厚非啊。
但是呢。
呃，我们作为面向对象设计啊，特别是学过设计模式的朋友呢，应该有一种思维层次，就是你不要去静态的看一个软件。
结构的设计。
而是要动态的来看啊，这也是我们课程里面非常重要的观点，就是呃用用一个简单的话说，咱们作为程序员要有一个时间轴的概念。
这就很多领域的问题啊，如果你静态的看问题，其实这个问题你暴露不出来的啊。但是如果你加一个时间轴之后呢，你就会发现这个问题的，你的角度就不一样。
对吧，那我们来看，当我们加上时间轴，也就是我们考虑到了问题未来的一些变化的时候呢，就是我们刚才在p p t 里面这里写的，对吧？
第一呢。
有没有可能未来还可能支持？
啊，比如说呃日本啊，比如说法国的税法啊，这是很有可能出现的一种业务变化情况，对吧？因为。
我们说你的用户或者你的产品经理刚开始告诉你的需求，是啊，我要支持中国、美国、德国，但是业务发展很快，对吧？
有变化很快很快可能会支持不同的国家。那这个时候呢，假设咱们啊现在有这样一个需要支持法国，对吧？要支持法国的话，大家应该怎么做啊，这个问题。
很多朋友很简单，能够想到第一个你要在这里面改这个枚举类型是吧？f 二。
啊，from 二x 对吧？tax 这样一个加一个枚举类型。
加完这个枚举类型之后呢啊注意我在这儿加一个注释啊，这是一个什么更改？
啊，大家想一下啊，我我说这个更改实际上是我想提示各位，我我们之前讲过一个设计原则是吧？大家想一下啊。
计原则是哪个设计原则啊？
这是。
我们在这里要补这个af l s，对吧？
啊，再再去针对针对法国怎么做，对不对？然后这个地方。
啊，是不是啊，当然我们可以用这样一个代码格式把这个放大挂放上来。然后呢这个是不是也是个更改。
这个违背了一个设计原则，对吧？哪个世纪原则，就咱们最早讲的时候有一个叫做开闭原则，对吧？开放封闭原则。
这个原则是怎么讲啊？
对对，扩展开放，对更改封闭啊就类模块应该尽可能的用扩展的方式来支持未来的变化，而不是去。
找着源代码直接去改的源代码的方式来面对未来的变化，对不对？那刚才咱们做的这个第五行这样的做法以及。
第二，十三行到二十五行具体算法实验我不写了啊，就是二十三行到二十五行这个在内部啊，这都是更改，对吧？这个更改我们说过那。
他是违背开闭原则的啊，因为其实他他带来很大的一个一个复用性的负担，对吧？就是说你的软件要。
重新更改，重新编译，重新测试，重新部署啊，一堆代价就出来了，对吧？
然后我们说尽可能用扩展的方式，怎么样扩展的方式来解决这个问题呢？
这个这个其实就慢慢引出我们strategy 设计模式啊，是怎么解决这个问题的。好，我们来看咱们代码中间的第二个例子啊，怎么解决这个问题，我们现在不用枚举类型来实现了。
啊，不用这个枚举来实现，我们把实现了一个叫做算法侧税法策略的这样一个鸡肋。
啊。
所以这个鸡肋呀，the base class. 啊不是那个。
那个寄的肋骨那些积累啊啊。this class 啊，基础类啊，tax strategy 这个基础类啊，它里面有个calculate 这样一个方法。
啊，这个方法那是一个在我们这里面定义它是一个纯虚方法啊或者呃抽象方法啊。这个方法呢我们放了一个呃作为一个算法上下文啊，就是他可能需要。
啊，嗯取得一个参数对吧？就这样一个康太子啊呃然后返回值，比如说是double 啊，呃当然作为一个鸡肋啊，就是我们的在cg 里面的设计，大家要注意。
任何一个鸡肋都需要加一个他的机构函数，要把它声明成虚的，哪怕它是器官函数，你觉得不需要写，对吧？啊，编译器自动生成是够用的，但是呢。
你也应该去写一个啊，也要写一个虚的析构函数。
啊，这个否则这个多态的delete 会出问题啊。
好，那请问这个鸡肋之后呢，接着大家来看我们对于中国的税法，美国的税法，德国的税法怎么实现呢？
就在这里啊，当然呃还是我强调的规范的情况下，实际上咱们这个类应该单独放到一个文件里面，对吧？不应该把虽然四家语法也支持把多个类放在一个文件。
啊，但是我们在工程上实际上是不推荐这么做的。呃，我在这里讲课的便利性，为了让大家快速的看完整个代码，我把它放在一个文件。
但并不表明大家在正式的这个工程开发中间应应该这么做啊。
好，那我们看cn tax 假设在另外一个文件里面，我放了这样一个text strategy，它叫继承这个tax strategy 啊。
然后呢。
使用这样就是over or right 啊，开口的这个方法，然后把那个它实现中国税法的计算的这样一个算法呢。
规则呢写到这个虚函数里边。
呃，其实如果对比的话啊，就是刚才这段代码我把它摘出来啊，大家来看一下这段代码。
这段代码。
其实十五行这段代码其实就是跑到这边十二行啊，就就就是跑到这里。然后这边十八行的代码啊，然后我们就要先写一个已有的states，是吧？
美国的税法，然后给他塞到十九行这里。
然后呢。
再来看德国的。
对啊。
德国的税法呢，我们仍然是。
在这里生成一个de 的tax 啊，给它塞到这个tax 啊继承子text strategy。然后呢这样一个渲染树放到二十六号。
那就简单来讲，我们把以前的一个一个的算法变成了我们这里边一个一个的text。stressed is the 子类。
好，然后呢，cu the order 怎么写呢？cu 早点。当然这个里边有各种灵活的写法啊，我们先来看最最直观的一种写法，就是我三十五行这儿放了一个text straight 这样一个。
指针。
所以这个指针呢我们是一个多态指针。
你必须放一个指针，注意你不能放不能放一个对象啊，这这是一个抽象类，对吧？你不可以放一个对敬啊，而且你一旦放在放上一个对象的话，他就没有多态性了。
你需要有多态性，所谓多态性就是你这个指针呢它要支持对吧？它指向不同这个text string age 的不同的子类啊。
好，那这个time strategy 就放当然就是特级特殊的情况，下放饮用也可以啊，引用是有趣，具有多态性的对吧？就是你你可以声明一个tax strategy 这样一个引用，但是。
呃，极少这样做啊，就引用还有其他毛病啊，我这里就不赘述这个问题啊。但是我们说一般来讲你要实现多态的变量的时候呢。
调用指针。
好，那个这个指针呢我们在怎么样去创建它呢？我们会推荐我们后边讲的一个叫做工厂模式的方式来创建它。
啊，当然共享模式在这个部分有有一些好处啊，我们现在先简单的了解，就是说不需要我们把右边嘛，对吧？就是你有一个实际的对象硬编码到这里，而是用一个外界传来。
的一个strategy，the factory 这个factory 调用一个new strategy，它可以返回出来。
可能是中国，可能是美国，也可能是德国的一个一个一个子类的具体的对象，对吧？这一区返回哪个？
是由工厂来决定的，不是由我们这个本身这个类所决定的啊。好，当然这个对象因为是我们说在工厂内部他返回的还是一个堆对象啊，这是确定。
这是必须必然的啊，他不可能返回栈对象是吧？那作为这样一个堆对象，你那你在你的吸构里面需要去负负责删除它，对吧？啊，当然这个这个。
不是我们设计的主周，我们主要来看下面啊calculate text。底下呢我们就需要首先要构建这个就是所谓这个算法的上下文的参数啊。
这样一个对象。然后呢，当然这个之前可能要做一些其他的事情啊，就是四十六行。我用省略号来表示。
然后我们最关键就看五十行这个地方我们就调用strategy calculate that。知道这个地方就是一个典型的多态，对吧？
这是一个多态调用。
啊，这个多态调用它有可能调用到中国的税法，有可能盗用美国的税法，也有可能调用德国的税法，对吧？呃，需要依赖于那个strategy。
next three, give 我们返回的是一个什么样的对象类型啊，他就会找谁的方法调用啊。
好，那这里呢其实是首先。
这个新的做法我们说相对于啊刚才这个做法有什么样特别的好处吗？直观的来看啊，但。
直观的来看好像。
呃，功能是一样的对吧？就是说都能实现这样的一个做法。
呃，但是呢我们说要比较好处，咱们设计模式领域要比较好的，就要放到时间轴里面去看啊。
嗯，那同样的我们也假设一种变化啊，假设现在出现了什么？
啊，就是刚才说的法国的需要支持法国的业务，对吧？那好，我们需要加一个法国的这样一个tax，这样一个g 呃一一个一个子类是吧？
那怎么做呢？我们在这个新的做法里面，就是要我这里面啊用。
这样一个方式啊来表示，比如说class。
f r tax, 然后继承一样的public tax strategy。
呀。
然后在这个地方呢，我就一样的做法是我需要写一个啊继承这个。
开q late。
啊，costs. 
context. 
然后呢，context 是吧？
好，这样来做，然后我就针对这里面啊，我针对针对法国的一个一个算法，对吧？就就就在这里面去实现了啊。
好，那当然这样实现了之后呢。
大家想一下class 这个sales order 要不要要不要动啊？
要不要懂，不需要动的对吧？
当然有些朋友说人那那个那个法国会会怎么样在这里面去去被被弄弄进来呢？现在就要看你strategy 这个这个factory 的选择。
啊，strategy factory 如果他是他内部支持法国，或者你选择了法国，那他创建出来的对象就支持了法国。那这个五十八行就自然掉。
多态调用就会找的啊，是吗？就是咱们赛若事，咱们三十五行到三十七行之间的这样一个法国的税法计算。
是吧？
所以呢大家看cu the order 在这个全场全过程中间是不需要变化的。
对不对？也就是用我们面向这样的术语，就是得到了复用性啊，然后呢这个这个做法呀。
就是咱们刚才三十三行到三十九行，这个做法是一个什么样呢？我们说是一个扩展是吧？实际上你是需要在一个新的文件里面。
添加一个新的类啊，然后用线，比如说有些编译，这是一些增量编译，对吧？你就单独编译它啊，然后。
你说把它单独编译成一个da l 啊，加进来，这都是可以的，对不对？那这个就维持了啊，我们刚才讲的就是。
遵循了我们刚才讲的那个开放封闭原则，对吧？就第二种写法实际上是遵循了开放封闭原则。而第一种写法。
要去改这个枚举类型，然后要方法里边内部去补这些代码啊，补这些代码，那就是打破了什么。
开放封闭原则违背了付佣金，但谈到复用性啊，有些朋友可能会这样说，哎，李老师就是说我这个虽然我是在改这段代码，二十三行到二十五行代码。
但是我十四行或者我从十一行到二十行，二十二行这段代码我都没有改变啊，他的复用性都得到了保证啊，他也在复用啊。
ok 这个复用注意是打引号的啊，打双引号的这个复用不叫富有啊。我我这我这一点强调面向对象，尤其是我们设计模式领域讲的复用性。
是指的什么编译单位啊，就是二进制层面的复用性。我们一般认为啊源代码级别，比如说你把这个源代码拷贝了一一段代码。
从a 的地方粘贴到b 的地方，这个不叫复用了啊，这个不叫费用，那个叫粘贴源代码，那不叫富游啊。呃因为我们真正的复用指的是什么？
你编译了之后啊，代码写过之后，编译之后，然后测试之后，部署之后是原封不动的啊，支付二进制意义的单位服用。
而不是源代码片段既的服用啊片段级的那那个是拷贝粘贴。
而而且啊不过且不谈那个就是即便。
就这段代码来来讲啊，有过代码经验的朋友就知道，其实呢你在一段代码底下啊去补一段代码。这个行为呢呃有些人说我保持上面的不便肯定没有问题的。
个保证是很难做出来的啊，这想象很美丽。但是你真正在实践开发中间的话，你会发现你在一个方法后边添代码的时候，你往往往往会打破这个方法前面的一些代码。
会把他代码前面部分引入一些bug。啊，这是这是在这个这个开发工程学里面经常会出现的一种问题啊，所以我们对源代码级别的这种拷贝粘贴我们是不推荐的。
啊，我我而且我们压根就不称他为副勇气，真正的复用意义是编译单位的复用性啊，而只有我们在第二种情况下，我们实现了啊这样一个strategy 模式。
啊，我们才他才叫什么？
二进制意义的复用性才满足了我们什么开闭原则，对吧？就是他是一个扩展式的方式。
好，那这个strategy 的模式其实就从打这儿来的啊，我们来总结一下啊，来来看一下这个刚才看了代码，大家首先。
对比两种代码对吧？那么我们回到p p t 来再来这个。
对照来说一下，首先大家看如何在运行，是根据需要透明的改变对象的算法啊啊那strategy 模式讲的是定义一系列算法。
把他们一个一个封装起来，并且使他们可以互相替换啊互相替换了这个词儿咱。
如果放到这里啊。
我这也是用了。
一个。
关键词叫变化，什么叫互相替换，就是知识变化啊，我我我我一直有这样的一个一个。
嗯，建议啊就是大家去自己模式啊这个教材啊或者各个方面的东西，你一定要能看得出来哪里是变化的，哪里是稳定的。对。
吧，所以这个呼吸支持他们，使他们可以互相替换，就是支持他们的变化。该模式使得算法可以独立于使用。
再看什么叫独立于啊？
我独立于你就是我是稳定的，就是我可以保持稳定，对吧？就是你变化的时候不不至于导致我也变化啊。
所以湛然湛然这个sales order 就是独立于这个这个税法的这个变化，对吧？c o order 的实现是稳定的。啊。好，这是我们的关键词，稳定的。
吧。
啊。
呃，就是使得我salur 的稳定，然后你的算法可以随便随时在变化啊，那这个变化是通过扩展的方式，在我们面向对象领域啊，我们使用的是扩展的方式。也就说子类化的方式来支持他们的变。
话。
好，那这是g o f 啊在设计模式对这个strategy 设计模式的一个定义啊，我希望通过这样一个解释，大家能够去理清他的一个关系。
好，然后再来看一下这个类图，看这个类图就很清楚了，对吧？大家看这个。
这边啊左边这个context 实际上就是我们刚才那个c ows order 啊，然后这边的这个strategy 就是咱们那个text strategy，对吧？
呃，他说的呃，一般意义上经常是放一个方法啊放一个方法，当然也有一些特殊的情况会放那么相关的两两。
三个方法，但一一般方法都不多啊。
嗯。
还是一样的遵循我们呃之前讲课的一个一个一个模式嗯。
我们把把这里边的啊，所以稳定的部分。
我把它圈起来，用红色的笔把它圈起来。
大家看一下稳定的部分，就是咱们上面的对吧？然后变化的部分呢我用蓝色的笔把它圈起来。
大家看这个底下的这个concrete strategy a 是就是我们刚才相当于cn tax 对吧？然后我们concrete straight。
就相当于咱们刚才u s tax，咱们现在的concrete pretty say，就相当于咱们的de 啊呃the tax 是吧？
但他们都是可变的啊，也就是将来可以增加法国，增加日本，增加更多的国家。
然后当我们的鸡肋呢啊就是这个strategy 和他的相关的这个使用，它的类型就是那个sales order，就是属于咱们红色的部分。
是保持不变的啊，就任何一个设计模式啊啊啊我们说除了啊咱们讲的设计模式里面，除了极个别的，像那个新构成这样的模式之外。
我们绝大多数模式都是可以用这样一个观点，就是你找找出他的稳定的部分和变化的部分啊。
好，那我们接下来来做一个呃总结来看一下。
strategy 设计模式呢，它和它的子类一位组件啊提供了一系列可重用的算法，从而使得类型可以在运行时。
大家注意啊，我们一直在强调这个词啊，很多朋友乙就是对这个词可能还不敏感啊。运行是。
那我们讲到运行时啊，支持啊各个算法之间的切换啊，方便的切换。
这个这个水位运行时，其实到了回到我们的代码啊，就是咱们这里。
这个就是运行时对吧？就是我通过运行时传递的一个多态的对象。然后它在运行时就支持多态的调用。
啊，简单的时候在运行时就支持了一个灵活的变化，对吧？灵活的变化。
然后呢strategy 设计模式啊，我们这里讲啊就是说。
他提供了用条件判断语句另外的一种选择。
呃。
条件判断语句就是咱们这里面刚才讲的a f l s 对吧？其实我这里面需要强调一下，就是在你的代码里面，一旦出现a sls 的话。
常常来讲啊，他就是呃这个strategy 模式出现啊需要的一种一种特征。
啊，这个大家如果读重构啊，马琳福勒写的重构这本书的话，你会看到同步这本书里面有一个具有一个条款叫做switch case 散弹是吧？
啊，或者是这个嗯呃就就是呃。
a c l, s 对吧？switch case 其实都是一个意思啊。
简单来说。
这个地方因为为什么我们不不推荐大家用l a f l s 或者switch case 啊？
实际上大家有没有从这里面看出来。第一呢，如果你用了a f l s 这种语句的话。
他。
是一种什么呃结构化时代的一种分而治之的设计思维，是吧？这是如果是af 这种情况啊，怎么做？
这种情况怎么做还是这个情况怎么做，这是分而治之的，对吧？我们说结构化的设计，这种分而治之的这种思维其实不太好啊，那你是可以用面向对象的抽象来解决他的。
第二个呢就是说一般来讲啊，a s l s a l s if f else, if f 这种结构写下来，大家都有一个判断，就是说。
那你你这三种情况完了之后，你还有没有第四种情况，你未来会不会有第五种情况？这六种情况对不对？如果你有的话。
就是典型的strategy 模式，对不对啊，就是支持未来的扩展式的变化嘛，以扩展的方式支持未来的变化。当然我这也要强调一下。
那是什么时候？就是说你这个代码里面出现了acl s 你不要去想pretty 模式。
有没有这种情况也有，对吧？就不是绝对的啊，不是说除了出现acs 就一定要有四百车。
那我们说只有在sls 是绝对不变的情况下。
啊，比如说你有三种情况，两种情况，这几种情况是绝对不变的。举个例子，对，如果你这个程序是根据性别来判断的，对吧？来判断你这个程序了。
以af 对吧？这个这个什么性别是男性mail else 吧。这个这个这个性别是女性的时候。
那我们说性别这个问题不太会变，对吧？是吧？这个世界上只有男性和女性这两种。
啊，对不起，这这有些朋友不一定承认这个事情，对吧？当然当然那我们再举另外一个例子吧，刚刚的例子不恰当啊，再举一个例子，比如说一周有七千。
对吧这副忙内做什么？its tuesday, if we incc 做什么，对吧？那那一周有七天这个事情我是不可能变的，对吧？
人类再怎么演化再怎么进化，不可能有一周有八天这个事情出现了。所以在这种情况下，我们说是绝对稳定不变的东西，你是可以用a fs。
啊，但是咱们想一想啊，回顾一下自己的编程经验里面，在绝大多数情况业务场景底下，业务场景的变化是非常迅速的，对吧？常常都是。
过一段时间就会加一种情况。过一段时间就会加一种情况，对吧？那么这个这种场景就是我们说a sls 特别需要小心的。
是吧用马丁福勒的话来讲，就是你看到af lx 就是就是相当于闻到了代码里边的这种bad smell 啊，一种坏味的。
啊，那么你应该很敏感的想到啊，哎这个时候是不是strategy 设计模式应该去去使用了啊，呃可以这样说吧，百分之八九十的情况啊。
你看到a fels 都应该去想一想啊，大概是pretty 的模式是可以可以适用的。
好，那么所以我们刚才有一句这句话啊叫做含有许多条件判断语句的代码呢，通常都需要strategy 模式。
对吧？
嗯，至于还有一句话啊，其实最前面我们曾经讲过啊，有一句话叫做有时候支持不实用的算法，也是个性能负担。这个地方我简单说一下啊。
就是呃虽然这不是strategy 模式的主要价值啊，嗯简单来说，如果比如说在这里面a c 二s 很多的时候呢。
但是你你比如说你在某种场景下，比如说你这个软件装到中国的话，那他肯定就是就是指调用这段代码，对吧？十四行到十六行指标有。
然后十七行到二十六行这段代码就一直不不被使用，对不对？
或者如果你是装到这个德国的话，那前面的代码就是这这两次判断都是十都是肯定是失效的。在也是常常不备用的，所以这个时候就会有一些个性能负担。
啊，而且在这里面就是你整个代码段里面有很大段的代码是被装载到代码段里面呢，但是实际上却不被使用，是吧？
但是呢这里边啊strait 二呢就不会存在这个问题，对吧？十二点二就是说他因为他在运行时呢，加载哪个塌，一般的执行的时候，他就直接调用那个方法了。
呃，我们一般把这个叫做代码具有良好的本地性啊，或者讲呃这呃这个这个话稍微解释一下，就是实际上你这个这个时候你的代码。
我们知道在运行的时候，代码在代码端里面，对吧？代码段加的内存里面最好的模式是加载了什么c p u 的高级缓存里边是吧？那个执行的最快。
否则的话你带了，但如果过长的话，你就需要有一些东西可能要放到什么主存力点。是啊，就放不到高级缓存里面，要放到主存里面，甚至极端情况下以储存的放不进去，对吧？你内存如果过小的话。
也也你你要放到什么虚拟内存就硬盘里边，对不对？那这些都是不太好的做法的话，就是简单来说不用这种模式的话，就是这这个是像这种a c l s。
你有很多的acs 的代码，其实是不不会被真正使用的，但是却要被迫被装载到。比如说。
c p u 的高级缓存里面，从而把你的缓存位置占用了。啊，所以你就不能够以其他的代码就不能很好的在缓存里面被执行。
就可能被被迫挤出几刀几刀储存力量或硬盘里面。那使用了strategy 是模式的话，在这方面会缓解这个问题。当然还是我们讲的threading 模式。
主要不是解决这个问题的啊，就是对性能问题是有一个呃有一个顺便的好处顺带的好处它主要解决的还是咱们刚才讲的这样一个。
呃，就是用扩展的方式面对未来呃算法层面的需求变化。
呃，最后一句话啊，如果strategy 对象呢没有实力变量，那么各个上下文其实可以共享同一个strategy 对象呢，其实就是说strategy。
在某种层面，你是可以用我们后面讲的一个singleton 的来设计的啊，从而来节省对象开销，对吧？比如你中国的税法只有只有那么呃呃里边如果没有一些。
实例变量的话，你你就只创建全军一个对象就可以了啊啊具具体这个模式呢，后面single 会会再讲啊，这这也不是特别特别重要的一个。
啊，strategy 的部分。
好，那我们今天呢这个strategy 设计模式呢就谈到这里啊，谢谢大家。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br><span class="line-number">177</span><br><span class="line-number">178</span><br><span class="line-number">179</span><br><span class="line-number">180</span><br><span class="line-number">181</span><br><span class="line-number">182</span><br><span class="line-number">183</span><br><span class="line-number">184</span><br><span class="line-number">185</span><br><span class="line-number">186</span><br><span class="line-number">187</span><br><span class="line-number">188</span><br><span class="line-number">189</span><br><span class="line-number">190</span><br><span class="line-number">191</span><br><span class="line-number">192</span><br><span class="line-number">193</span><br><span class="line-number">194</span><br><span class="line-number">195</span><br><span class="line-number">196</span><br><span class="line-number">197</span><br><span class="line-number">198</span><br><span class="line-number">199</span><br><span class="line-number">200</span><br><span class="line-number">201</span><br><span class="line-number">202</span><br><span class="line-number">203</span><br><span class="line-number">204</span><br><span class="line-number">205</span><br><span class="line-number">206</span><br><span class="line-number">207</span><br><span class="line-number">208</span><br><span class="line-number">209</span><br><span class="line-number">210</span><br><span class="line-number">211</span><br><span class="line-number">212</span><br><span class="line-number">213</span><br><span class="line-number">214</span><br><span class="line-number">215</span><br><span class="line-number">216</span><br><span class="line-number">217</span><br><span class="line-number">218</span><br><span class="line-number">219</span><br><span class="line-number">220</span><br><span class="line-number">221</span><br><span class="line-number">222</span><br><span class="line-number">223</span><br><span class="line-number">224</span><br><span class="line-number">225</span><br><span class="line-number">226</span><br><span class="line-number">227</span><br><span class="line-number">228</span><br><span class="line-number">229</span><br><span class="line-number">230</span><br><span class="line-number">231</span><br><span class="line-number">232</span><br><span class="line-number">233</span><br><span class="line-number">234</span><br><span class="line-number">235</span><br><span class="line-number">236</span><br><span class="line-number">237</span><br><span class="line-number">238</span><br><span class="line-number">239</span><br><span class="line-number">240</span><br><span class="line-number">241</span><br><span class="line-number">242</span><br><span class="line-number">243</span><br></div></div><h2 id="_05-观察者模式"><a href="#_05-观察者模式" class="header-anchor">#</a> 05.观察者模式</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>好，大家好，那我们开始我们啊c 佳佳设计模式的。
观察者模式。i 啊呃这这个英文叫observer 啊。
首先我们来看一下观察者模式啊，他解决什么问题。
他仍然是一个组件协作模式啊，那么我们前面已经学了这个template method 和strategy。
而不周这个模式呢，幼教啊啊在有些领域又叫event 啊，其实讲的是一个意思。
呃，他解决的还是我们这个框架和应用的这个协作问题。我们具体来看一下啊这个模式他的一个解决的问题的一个动机和场景啊，是在我们。
软件构建的过程中啊，我们需要为某些对象建立一种通知依赖关系啊。
呃，一个对象啊，或者我们叫目标对象，它的状态发生变化的时候呢，他希望其他的对象。而这个对象呢就是个数不等。
啊，呃所以我们这里说法叫所有的依赖对象啊都将得到通知。
那么如果这个依赖关系过于紧密呢，是不太不太好啊。我们一直提倡的是一个松耦合。
好，我们来。
回到代码对吧？啊，生命the code 啊，我们看看代码层面是一个什么样的表现。
呃，我们假定这样一个设计的场景啊。
呃，一个一个需求。比如说我们只要再有一个座一个文件的分割器啊，第一呢一块儿呢我们是一些需要一个界面啊。
大家知道在这个文件分割器呢，在这个时代可能在嗯用的人比较少。然后上个时代的吧，十年前的话，文件分割器还用的蛮多的。因为呢。
那个时候还是一个我觉得是一个三寸盘的时代。那经常要把一个大文件拷走，对吧？那考不走，比如几兆的文件，你那个。
一点四四兆，那那个那个那个那个呃很小那个盘是考不走，所以你需要把经常把一个大道境分割成多个文件啊写带走。
那么这个时候呢。
假定我们是做这样一个需求吗？
那么比如我们需要首先要有一个界面啊，那么这个main form 呢大家看就是一个界面，当然还还是我强调的，我们讲的是一个伪码的设计。
啊，所以呢我们只是把主干的设计代码把它展示在这里。其他跟我们这个设计不是那么相关的，我们就没有写啊。
所以大家会看到，比如说我们这个成员呢，他会去继承一个，比如说付类form 啊来表现一个一个一个windows 的一个一个窗口界面啊。
嗯，然后这里边呢我们主要的是有点什么两个控件，一个是收集那个呃用户选择那个大文件，它那个文件的啊带着名字的一个全路径。
然后第二个部分呢是用户需要呃输入，或者通过一个up down one 的一个一个控件来输入。啊，这个他希望分割的文件个数。
啊。
好，这两个是关键信息了，其他信息也许在界面上也有，但不是我们这里设计的关键啊，我们通过他呢，然后你说这个八千一啊click。
啊，至于这个巴顿一clay 可是怎么被点击掉到这个方法我们不关心啊，我们来看在这里呢，我们首先发现you click 的时候，我们收集到用户的两个输入的参数信息。
然后传递给啊file splitter。
然后feirce bitter 呢去调用这个split 方法，然后我们再来看这个spate。
就fell better，bitter, feels bitter. 也很简单啊，只要我们就是放两个成员变量啊，分别负责他的文件路径和它的文件个数啊。
那么通过一个构造器，然后复制给这些参数赋值啊，这个都很简单，没有什么太大的问题。然后呢split 方法。
啊，我们仍然是用一个伪码来表示啊，就是首先呢我们知道分割一个文件的做法，往往是首先你要去读取那个大文件啊。
当然这个也是分批次去读取啊，然后呢再分批次向小文件里面去写入啊。比如你要分割十个文件。
那么这个时候。
你要分十次向每一个小文件里面啊写实写诗词啊，这样的话就可以。当然这个过程中牵扯到，比如说你要做很多的缓存处理啊等等。
啊，但是那都不是我们关心的重点啊，我们现在假设啊我们做了这样一个设计啊，这个设计底下呢。
大家会看到呃，目前来讲这个任务是完成了，对不对啊？就是想让我们的算法都写的很正确啊，然后呢文件分割九分割成。
啊，好，那我们现在假如说我们有一个用户需求啊，这就是我们。
要要看我们观察者这样一个设计场景啊，那么有一个用户需求，他希望呢就是说这个粉业分歌有时候这个文件特别大，对吧？那么上个时代的文件小。
这个时代呢，比如说一个文件上记的文件比比皆是，对吧？如果一个文件上很g 那我要把它分成，比如十个啊啊一百多兆的一个文件。
那这个时候呢，这个文件分割会花时间很长，对吧？读写文件。那么你这个时候需要提供一个，比如说我希望提供一个进度条。
一个进度展示，这是很自然的一个需求，对不对？
好，那么假如这样一个需求提出来了。
各位想一想啊，如果你请你来做这个设计，你会怎么做设计啊？就我们希望在这个界面上提供一个进度，我们先用最朴素的想法啊，很多人最朴素的想法立即。
当然要提供进度条，需不需要在界面上提供这样一个。
pro. 
grace bar. 
啊。
progress 把这样一个成员是吧？
那么作为这样一个成员呢，那么你。
需要。
啊，通过某种方式让那个分割。
分割的进展分割进展在哪里呀？在这里对吧？在这个这个循环里面啊，在false 别去提供给他去更新这个progress bar 的一个值，对不对？
那大家可能会想到的一种做法是什么呢？比如说。
嗯，我先来写在这里。
是不是也也会可能会存在要放一个progress bar 这样的一个需求。
啊。
好，那当然在这个地方呢。
比如说我就可能会去做一个事情啊。
m. 
而啊。
i'm progress bar. 
比如说他的假设它有一个set value。
啊，这个晒太白量呢，比如说是i 啊，然后呢比如说因为那个i 是一个从零开始，对吧？所以我爱加一下一。
然后呢，在除以。
啊，m. 
m, file number. 
是不是？
对吧就类似这个这个这个就是更新进度条是吧？
是这样一个设计。
当然想啊，就是我第一种做法是这样一个。当然这个这个m progress bar 呢你。
你其实比较好的做法可能是需要在这里面去做一个判断，是吧？
if fm 啊不等于。
now 是吧，这是p tr 啊。
对对，是这最好是在这里做一个这样的一个一个判断啊。
就说如果一有这个进度条的情况，下午再去更新这个进度条，对不对？
那么当然这里边呢你在团餐的时候，是不是也要去设置设计一个这样的一个参数啊？
嗯，没有把这个拷进来。
我把这个progress 吧咖啡进来啊，假如说这是外界传的一个参数。
然后呢，我在这里呢。
就把。
咱们这个i m progress bar 作为一个成员初始化列表的一个住处化方式啊。
啊，我的progress bar 把它这个参数找到啊，这样传递进来。
好，这样的一个做法啊，中规中矩，对吧？
当然你在初始化的时候呢，比如说这个地方是不是就应该把咱们这边的一个。
osby 也传递进来。
假如果你传递的进来，大家想象这个split 方法调用的时候，是不是在这里面就会不断的更新到我们的进度条，对吧？那么咱们如果这个界面可以正常的显示出来，你就会看到那个进度条不再往前。
手对吧？
好，那。
呃，我我想就大家呃一般的程序员啊，绝大部分程序员嗯，比如刚从学校里面憋出来的程序呢。
都能想到这一步，对吧？就说。
用户提供接入一个需求，或者你们的产品经理提供提了这样一个需求。那你不加思索的第一啊反应就是这样实现，对吧？绝大多数情况下啊。
但是啊我们说这个时间当然有没有问题呢，是吧，有没有问题？
当然是有问题的，如果没有问题，老师就不在这里讲，对吧？那大家思考呀，他会他有什么问题？
每次当我提出有什么问题的时候，大家就要回想什么，不要去想用哪个模式啊。
大家应该想立即要想到什么？我们八大设计原则啊，从八个世纪原则里边。
哎，这样的一个设计方法是不是违背了我们某个某某些或者某个设计原则。
呃，可能有些朋友已经想起来了吧，这个违背了我们哪个设计卷子。
就是我们讲的第一个第一大设计原则依赖倒置设计原则di p 对吧？
依赖倒置原则。大家再想一下，回想一下是怎么讲呢，对吧？
高层模块不能依赖低层模块啊，二者都应该依赖于抽象啊，抽象不能依赖实现细节。
啊，实现细节应该依赖抽象啊，那我们来看看这里边产生了什么方面的不良依赖啊。
呃，大家看这个里面放在这个字段啊，我们说依赖啊呃我们再强调一遍什么叫依赖，对吧？a 依赖b。
意思就是a 编译的时候必须要存在才能编译通过。我们讲的依赖都是编译时依赖啊，除非我们明确提出这是一个运行时依赖。
啊，我们才会说啊，他是个运行时以来，否则我们在我们设计模式这个课程里面讲了依赖关系都指的是编译室以来。
好，第六行，这个就产生了一个什么编译时依赖。
对啊，那这个依赖关系。
其实不太好，为什么呢？这个progress bar 呢就是我们在呃依赖倒置原则谈的那个实现细节。
为什么说他是先季节，大家想一下，就今天你设计这样一个啊文件分割，请你用的是一个progress bar。
对吧，但是你你能保证明天贵一段时间，这个还一定进度通知是以一定是以这种方式来展现的吗？
不一定进度通知一定只用方式展现，对吧？进度通知可以有很多种展现方式。比如说我也许在界面上放一个label。
是吧那么那么这个label 我希望直接把那个百分比显示出来，比如百分之九十九、百分之八十五、百分之七十五这样子对吧？也有可能呢我甚至这个程序呢都不是一个windows 或者是一个窗口。
程序我有可能是一颗，比如说控制台的程序，我希望在这个控制台上呢去打一个一个的点来表示他有进展。
啊，表示这个这个文件正在被分割啊，这不适用这样一个呃界面的呃呃展gui 的界面的形式。
所以这里面第六行写的这个progress bar 啊，就会给我们带来一个什么，就实现细节层面的一个需求变更的困扰。
啊，我们我们讲依赖导致原则中最根本的在讲就是说为什么不喜欢是依赖实现细节。因为实现细节是非常容易变。
对吧？
就是说刚才咱们说的几种变化情况是极有可能出现的，对吧，那。
那么这个依赖就不好，那怎么样去改变变化呢？怎么样去去重构这个代码啊。
这也是我们讲设计模式课程啊最大的一个特点。
啊，我不太喜欢另一种讲述方式啊，我也不希望大家去期待那样一种讲述方式，就是两上去够高告诉你啊，我们这节课要讲观察者模式了。
然后然后把观察者模式的代码框给大家一讲，说这就是中央观察者模式其实这个吸收的非常的不好啊，那我更喜欢的一种方式或者我。
建议大家一种学习的方式，就是带着问题去思考的方式。啊，就是就是说首先看我们没有用这个模式的时候，他会出现什么毛病。
啊，这个毛病聚集体现了就是他违背了哪些设计原则啊，然后呢我们带着这样一个一个毛病原则的审视。然后我们通过重构的方式不断的来改变我们的代码。
改写我们代码，然后呢一步一步迭代到模式，就是我们讲的重构到模式。啊，好，那我们现在来看这个问题怎么解决。当然很多朋友。
立即想到这就依赖倒置原则给我们的一个说法是说，你不要去依赖a 而h 依赖a 的抽象基类是吧？
直观的是这样子的啊，所以你会可能会想，哎，我是不要依赖progress bar，我是不是那probus 积累是一个什么呢？可能是一个control base。
呃，积累对吧？可能是这样一个积累。
就是progress bar 的父类。但如果单纯的按照找这个类的父类的这样一个方式去寻找的话，你会发现会走入一个死胡同。
这当医械control base 的时候，你会发现这里面这边怎么办？
二十七号广州贝斯克没有set value 这个这个方法对吧？就是甚至都没有更新他这个界面，就是更新这个进度条的这个值的相关方法呢啊。
所以你会发现单纯找鸡肋实际上是一个很。
很粗浅的认识。
那这个时候呢，大家要思维层面要深入理解到。
我真正到底要解决什么问题？
对吧，呃那么progress bar 这个在这里面到底扮演了一个什么样的角色啊，那么如果仔细问的话，大家会发现啊progress bar 它实际上扮演的是一个什么？
依赖是一个通知是吧，它是一个通知啊，那么这个通知呢我们是不是可以用一种。
相当抽象的方式来表达一个通知，而不需要使用一个具体的控件来表达通知啊控件来表达。同时太低调了。
所以呢根据这样一个思维的这个认知呢，咱们就可以对这个进行一个迭代啊处理我们。
为了方便期间，我直接在我们这个类文件里面写啊，比如说我这里现在就写一个，比如说cla。
class. 
i progress. 
这个i 我表示一个接口啊，接口在咱们自己家里面，其实就是抽象抽象基类，对吧？好，比如说我这儿写一个virtual。
啊，void 啊都不管。
啊，然后这个do progress 呢。
我去传递一个值啊，比如说一个double 啊或者是一个一个一个float 吧啊。
对，就传递一个介于零和一之间的一个百分比的这样这样一个值啊。
好，传递这个value。
当然作为一个鸡肋啊，一般来讲还是要有一个咱们说的区域。
吸构函数是吧？
好。
那。
我们放假一个东西，大家看看啊，我们希望用它来去表达一种抽象的通知机制。
我们前面说这是一个通知控件。
对吧，不管是bar 是一个通知控件，现在咱们把它改了，改成了一个这样的一个东西。
所以大家对比这个上下了代码啊。
哎。
q. 
right? 
啊，然后这是一个什么？我们说是一个通知。
抽象的通知机制。
好，大家看一个是具体的通知控件啊。
一个是抽象的通知机制。
我们就从这一点上完成了，从具体到抽象的一个一个跃迁啊，这个很重要啊。好，那到了接下来呢。
咱们当然就应该把咱们的代码啊再做一些更改。
那么。
这个更改方式啊。
啊，这边。
是不是？那我们稍微。
我喝一點。命名规范啊方式这样来写吧。
然后这个是一个i progress。
哦，那啊比如说这个参数名字就叫i progress。
好，然后在这里面呢，咱们得到的就是i。
下划线。i progress. 
如果他不等于空。
呃，他有可能没有可能是空的话，那就是没有通知机制，对不对啊，那么这个地方。
其实我就可以直接去调用这个叫做do progress 这样一个方法。
对吧？
嗯。
当然了，这个考虑那个什么棋件啊，你之前其实是。
应该把这个呃改成float，对吧？否则那个那个出来是个整数啊float，比如说一个。
啊。
这个progress。
value 等于这个。
啊，然后呢再把这个值呢。
不管是。
在等。
这个去。
去除一下他，否则那个整数相除两个出来是个整数，结果是吧？
啊，那这样就可以了，对不对？就不快都铺不死啊。
好，那这样的话，咱咱们就得到了一个很好的这样一个。
抽象的接口啊来表达这样一个通知机制。
当然那接着这边怎么做呢？
大家来看。
这边的话就不能传progress bar 了，对吧？其实就是我们要解耦了，那就要传一个i progress 接口是吗？那这边的appropriate 接口怎么整呢？
再来看在这里啊。
public. 
我让您奉母去继承或者讲去实现。
high progress. 
在这里我也需要说一下，大家知道在c 加压里边啊，其实是支持多继承的，对吧？但是呢我们其实不推荐大家太多的去用c 加尔多继承。
啊，多继承会带来呃很多很多就是一些比较复杂的一些耦合性的问题吧。
但是c 家推荐一种多继承的形式是什么？就是以我们一般叫做一个是补的继承类，其他都是接口或者是抽象基类。
啊，其他都表现，这这个其实也是后来的语言，比如说像佳啊呃像这个呃c hup，包括嗯苹果的swift 的语言，对吧，都。
后来所支持的就是说你单继承只有一个父类，但是其他都是接口，这个其实也是打c 家的一个最佳实践过来的。
嗯。
学习设计模式啊有另外一个好处，就是帮助大家去梳理那些以前一些面向对象的观念啊，你说多继承对吧？在这里面去其实更多的时候是这样使用的。
呃，好，那然后我们把这个拿过来，就是这个这个方法。
邀约原封不动拿过来，然后我去实现它。
在这里呢，我怎么实现呢？我就是真正的去做什么。当前的progress bar 是吧？
然后呢。
set up value, 然后把这个value 塞进来。
是不是？
然后呢，我在这里当然就可以这个怎么传啊，大家想。
this 是吧。
this 四就是当前may inform 的这个对象的指针是吧，这个对象呢他显然是实现了i progress 接口了啊，那你把它传进来。
而他就实现了这样一个。
嗯，都programs 这样一个方法啊，那么在这里呢我们去防这里。边防progress bar 是没问题的，对吧？因为没inform 和progress bar 是一个。
本身是一个一体的对吧？或者他们的关系是仅有盒的，没有关系啊。
呃，大家看一下啊我们。
先重构到这里，其实已经相当成功的实现了什么？咱们依赖依赖倒置原则是吧？这把原来一个紧耦合的十三行结耦合的。
变成了十四行的这样一个松耦合。
你现在再去看的话，fields split 整个这个类有没有在耦合一个界面类啊，没有了是吧？没有耦合任何一个地地方的界面了。
所以我就可以独立的编译，是吧？
我可以不依赖我，我这样一个文件分割器写完之后，我将来可以把它放到一个windows 的界面里面，我也可以放到一个linux 的界面里面，我也可以放到一个控制台里边。
任何地方我都支持一种进度通知，然而这个进度通知是通过i progress 这样一个抽象接口来完成。
当然从形式上来讲，就是以前大家在这儿写的set progress 的这个方法是吧？
呃，就是progress bar set a value 的这个方法啊，跑到二十一行了，对吧？就是说形式上好像是从把代码，从以前从这个地方。
翻到了二十一行的这个地方。
但是这个这个呃变化是非常大的啊，就是从一个所谓的一个。
不良的耦合变成了一个良好的耦合啊，这个现在良好的耦合实际上大家如果现在画一下类图关系的话，你就会发现啊，它实际上是已经付。
符合了我们啊在这个部分已经符合了我们的依赖倒置原则，对吧？
好，那当然这个还可以在代码上再做一些比较。嗯，稍微那个什么一点工作。举例来说，这个地方呢你可以嗯。
写个protected。
然后呢，把这个再再加一个啊，就是我们稍微优化一下void。比如说啊on progress。
啊，这也是很多这个。
嗯。
嗯，这个。
设计里面所说可能会去做的一些事情啊，比如说这个时候呢，实际上我们把这个更新进度。
进度通知整个这个事情呢全部呢搬到这里。
啊，会更好那么一点点啊，或者讲。
然后这个里面呢再一个。
no. 
y 六。
然后这个progress value。
哦，那这个value。
啊，实际上当然这个这个判断应该是在这里做的啊，我把它拷贝下来。
好，但这样一改良之后呢，你会发现这个代码结构呢更。
更清楚了，对吧？更舒服。
啊，然后帮up progress。
对。
好啊。
大家来看这样这样子啊，就是只是做了一一点点小的调整啊，就把刚才这这坨代码给他分割出来一个。
一个受保护的方法。这个方法呢在某些框架里边啊，甚至于把它设计成一个虚方法。
以供子类可能对这个部分去改写也也是有的啊，咱这个改写有一定的意义。就是说你可以针对这个实现的部分啊，比如说这个是具体的实现，可能是一些其他的数据。
别挂我的呢，你可以去啊，当然这个不是重点啊这个词啊，一个一个小的辅助的改良吧，最大的重点啊，整个这个设计里面最大的重点是这里是四行。
其实各位做到这里啊。
针对这个问题，要我说已经是相当不错了啊。一般我们说呢这个设计呢是比如说工作个两三年的朋友。
啊，你建立了一定的设计的素养啊，那么这个时候呢a 呃就是我不要用前一种设计，对吧？就十三行的设计是。
我们知道是是不管三七二十一，先把结果出来，对吧？不考虑设计的品质的那十四行的这样一个设计呢是提升了这一品质啊，看到了耦合性的问题。
解决了。
但是呢这个设计里面其实还有还会遇到一些个小的问题，就是说。
如果我要支持多个通知呢。
啊，当然对目前这个这个具体的例子里面，有些人会说，如果多个通知，比如说同时我也可以在这儿写一个c lt 咋点啊，对吧？也可以这样去做啊，打一个点吧。
啊，没没走一步就打一个点。
嗯，针对目前这个例子啊是这样，但是有些例子里面他不容许你把这些代码放在一起，还是分离开来。好，也就是说。
需要支持什么，多个观察者。
我们我们现在其实只支持一个观察者，谁是观察者门缝或者讲这个progress bar 是吧啊，就是民奉母就是其中的一个观察者。
啊，但是咱们再回过头来看一看啊。
咱们当初这在谈这个观察者设计模式的一个场景的时候呢，就是说我一个对象的状态发生改变。我有时候我是希望我所有依赖的对象。
所以所有就是有可能有多个对吧？那么假如我们要支持多个怎么办呢啊？
比如说我在这里。
没有，我再写一个类，对吧？class, 比如说console。
对啊，不知道我。
啊，一个。
康总啊。
通知着吧。no no, ty f 啊，然后呢说这个类里边。
嗯，十二。
高挺爽。
哦，在这里边，比如说我要去呃实现那个，那我去也是要去继承，是不对啊，这样继承啊。
public progress 啊。
不然这这里面就是在实现这个接口了。
啊，写成public。
然后在这里呢cr。
对不对，是不是这样子啊？
那当然你你你这样写下的时候，你就会遇到一个两难的选择。第一个呢你是放this 啊，还是说我换一个，我写一个console of notify r。
呃。
然后呢。
cn 啊那么把这个cn 这样这样传递进去。那你每次这样传的话，你其实都只能传一个观察者。
是吧一个观察者。
所以这里边就导致我们的这个矛盾。那这个矛盾就是说怎么解决呢？其实。
就是我们这个改良版，我们继续改良，我们发现哦原来以前只能支持一个，对吧？因为你每次里边只能存这么一个，那我们现在要支持多个。
怎么做呢？当然很简单了，对吧？你想支持多个的话呢，就是在这里面加上vector 是吧？
迈克的这样一个真实吗？
然后这样。
这样一个m your i progress。
list 啊或者直接就写成vector 吧。
啊啊iii progress 啊，vector 当然。
那么这个就是支持了什么？支持多个啊。
就是多个观察者。
对吧？好，当你写下这个的时候呢，这个地方还要不要写这样一写，一般意义上我们都不再建议就是这个地方在传这个参数了。
我们就把这个参数给它去掉。
啊，这个也给他去掉。
啊，我们这个时候更喜欢这样，怎么选呢？就是我在里面。
第一个void，add. 
还。
progress. 
啊。
那这个艾呢？
我当然也是要放成一个a progress 这样一个指针是吧？
好的。
m. 
for vector, 然后。
啊，pushback 啊。
然后把这个i。
i progress. 这个加上去是吧？i progress. 
啊，就做一这样一个参数啊。
对不对？然后呢，再有。
这里。
人物。
i progress. 啊，是不是我在这里也要去把他再去。
这个人目这样的一个删除啊。
那通过啊，那当然这里面的数据结构啊，其实呃可可能啊这个这个呃the vector 这种这种方式啊。
并呃并不见得适合存储这个啊，因为你你你要考虑到那个删除的复杂度的话啊，可能会犯一个一个list 会比较好一点啊。
当然具体这个实现anyway，大家可以根据啊根据自己的一些。
需求来来设计相应的数据结构。
但是总的来说呢。
啊，这个。
昨天来说呢，大家要在这里边啊，就是说你要有一个add 和remove 来去表达，我可以随时去操作这个。
啊。
然后呢，当然这个。
具体啊这里边的这个这个实现啊，这里边的实现就是应该改一下是吧，应该应该换成什么？
换成我们说你。
你要支持啊，比如说对这个list 啊，它的一个。
你取他的一个迭代器是吧？比如说beginner 这样一个一个迭代器啊。
然后呢，具体来说在这里那么。
你拿到他的嗯begin。
讲一个迭代器。
然后啊当然你要去需要去写他相关的迭代器啊。
你说这个list 的啊。
it rat her 是吧。
然后。
比如说start 啊，然后呢再有一个取一个end 的迭代器。
然后等等这样接下来啊去。
也就是通过一个迭代的方式取让每一个元素，然后针对每一个元素里边的那个值啊，然后进行一个。
都progress。
啊，也就是说这个里边当然你需要去首先。
通过。
假设啊。
啊，i t e o r 吧。
i t o 啊，然后呢。
啊，然后你你vil 一个一个一个一个循环啊，如果这个不等于那个结尾的，这时候就一直。
啊，不等于。
啊，然后这个。
的。
and 是吧。
只要不等于他。
然后你就去访问，然后那个。
i t o 啊再加加是吧？
啊，总之总而言之，这里面用什么数据结构无所无所谓了啊。就是说你在这里面读progress 的时候，你要去便利以整个这个数据结构。
然后呢，取到他的相关的这个这个元素里面的值。注意注意这个元素里面的值啊，本身对吧？它是一个什么指针是吗？
嗯，拿着这个指针，我们要去访问那个do progress 是吧？
好，那这样一个a 的remove。
这样一个结构啊，就表达了我们可以支持多个观察者是吧？好，拿着这个呢反反向的来看，这里边就不是这样写了，是吧？反过来这。
这边看的话。
那大家的一个做法就是我在这个之前呢，我就可以拿着这个splatter。
然后呢，at 的那我们找一下这个方法。
但这个其实嗯规范上我们不太建议直接显现画下划线了啊，就比如说直接艾的i progress。
然后比如说this。
啊。
比如说再再加一个。
啊，我这个时候是不是就支持了所谓的两个观察者是吧？
啊，当然就这里面这这个过程中。
相关的内存管理啊，你需要做合适的一些安排和处理啊。
啊，那目前来讲就是主要的是咱们针对刚才那个版本进行了一个支持多个观察者啊这样一个方式。
然后你反过来，你也可以在下面呢去调用这个remove 是吧？
就如果remove 主要是和爱的相相对应啊，就是说如果你在某些情况下。
不需要。
某一个观察者或者多个关联庄，你可以通过这种方式去删除它啊。
好，那到目前为止啊，其实我们的观察者设计模式才算啊。
才算真这个才算真正的观察者说。
啊，好，我们来看一下啊。
嗯，回到我们ppt。
首先呢我们这里有这样一句话，就是定义啊。
对象一对多的一种依赖关系。
以便了。
当一个对象的状态发生改变的时候。
改变的时候，所有依赖它的对象都得到通知啊，并自动更新。
对，这里边很重要的就是说一个是一对多啊。
啊，另外就是说依赖他的对象。
会自动得到通知啊就得到通知并自动更新。这我们比如说他产生了一个我们讲一个松耦合的关系啊。
好，那我们来对呃看一下这个类图啊。
嗯，这个类图里边呢？
我先来说一下这里边的这个observer 啊，相当于咱们刚才那里边的什么i progress。
是吧？
里边的update 相当于什么呢？咱们里边的那个。
i 唉就是do progress。
在这里啊这个地方。
啊，然后这边的这个subject 呢，我们没有提出来啊，其实。
更正确的做法是应该什么？就把这个attach 以。
是这个attach 相当于我们那个i d 嗯。i visit teach, 相当于我们那个remove programs，对吧？the notify 呢相当于我们那个。
呃，就是那个叫on progress 是吧？就uns 大家看它里面放了一个for 循环的，反正就是对那个数据结构的一个便利啊。
呃，嗯。
退回来看一下，对着代码来看一下啊，就是这我们把这三个东西吧。
这三个东西这两个东西往下放一下。
四十行一直到五十八行这一段啊。
这段。
呃，实际上就相对应在我们刚才这个地方，对应到我们这个attach detach notify。然后呢呃。
官方的啊g o f 定义的这个设计模式建议是什么？可以把这三个方法再放到什么，放到父类里边，就放到一个鸡肋里边。
然后让那个my files bat 去继承那个积累，对吧？这个在某些框架也有这样的做法啊，当然有些框架没这么做，就这个框架就像我们现在这今天这样写。
直接就写在这个fields later 里面啊，咋还认为这个就是不是特别特别就是关系特别大的一个一个。
一个实现啊，就是说简单来说你放的是提出subject 和不提出subject，其实它都是观察者设计模式啊。
好。
那就是简单来说我们刚才写的那段代码，实际上是把subject。
和康create subject 合二为一了。
对吧那么也有一种分离的做法。
那么concrete 这里的congress subject 就是咱们的file splitter。
啊，简单来说就是那些什么主体对象啊主体对象。
然后这边右边咱们再看哦。concrete observer 是谁啊，就相当于咱们刚才那个may inform 或者是那个康。so no, no. 
是吧就是具体的什么观察者，具体的观察者啊，所以如果我们用一个方法啊，就是还是。
我们前上一个讲的的，我们把这个整个系统里边啊，观察者设计模式里面，设计里面稳定的部分，用红线来画。
好。
我这个。
这个用鼠标画那个话题啊，这个比在抖啊，所以画不齐。
啊。
然后。
大家了解这个意思啊就就可以了，就红色的部分是变化的部分。
蓝色的部分ll 少，红色部分是稳定的部分是吧？是我们系统中间应该去依赖的部分。蓝色的部分呢是为了支持我们的什么。
一对多的这样一个变化啊，这是我们的具体的观察者的这个实现和具体的主体对象的实现啊。
好，有了这个啊类图在对应的咱们刚才的代码关系里面啊，我想大家可以通过这个呢比较好的去抓住观察者设计模式的。
一个非常核心的啊东西。
好，我们。
总结一下。首先呢使用面向对象的抽象呢观察者模式，使得我们可以。
独立的改变。所以这个独立的改变啊是是是什么意思？
其实所谓独立啊，我我们通常说独立的改变的意思就是我。
我们之间的关系是一个松耦合关系，对吧？就我改变你不用变，对吧？从而使两者之间的依赖关系杂志松耦合。
咱们再来看一下谁改变谁便用该变。
就是你这边你随便添加多少个观察者，随你便对吧？就是你就按你自己自个儿去爱的吧。
我这边呢？
我这个结构是稳定不变的，对吧？大家看我整个这个结构是稳定不变的，假我可以支持任何观察者网禁放。
我这个保持复用性，一直保持复用性，对吧？那么大家就想你，你这个以后就可以支持对吧？各种各样的平台啊使用我这个文件分割器都没有关系。
就不会像以前十三行这样，就和具体的某一个平台的那个进度条绑死了，是吧？
房子就是紧耦合是吧？独立就是松耦合。
好，然后呢，目标发送通知的时候无需指定观察者。
啊，无需指定观察者通知会自动传播。
啊，什么意思呢？再回到代码。
我发送通知的时候在哪里发送，就是这个对吧？on progress 就是我在调用。
这个就是发送通知。
发送通知的时候，我不知道谁是观察者，对吧？
我不需要像以前一样指定一个progress bar。具体的障碍观察者，我是针对整个通知机制进行一个抽象的统治。
啊，同时可以自动传播是吧，按他们的规则自动传播。
观察者自己决定是否需要订阅通知。
对吧，就在这里，你自己决定是否需要订阅通知啊，十八行十九行，这个都是订阅通知。
订阅通知的意思啊，就是将来那边有通知，对吧？就会什么就会告知我这边我所以告知我这边就是调用我一段代码。
有。
好。
那。
目标对象呢对此啊一无所知。
对吧，就是我不需要知道你。
我就可以完成我的任务啊，这就是松耦合的真谛，对吧？
所以他们热模式啊，我也需要强调一下，他是非常常用的一个模式啊，他跟这个template method 模式啊一样的常用。
呃。
那有些朋友可能会说就是呃。
呃，没有我啊，其实你只要写过那样那样应用程序啊，呃百分之呃八九十的情况也是会用过的啊，一定会用我。尤其你写一些成熟的框架啊。
呃，几乎比如说像戛纳里边对吧？他知道家里面的主流的这个listener 的机制，就是观察者设计模式。线下二部里边的。
啊，这个咱们这个这个整个这个事件啊，在crh 里面这个这个观察者模式叫做a vent 模式啊，叫世界模式，它也是一个观察者模式的表现。
所以我们讲啊薄弱观念的模式是基于事件的ui 框架中间非常常用的一个模式。它也是啊那个我们说mac。
对吧这个这个比较大的一个架构模式里面，一个非常重要的组成部分。
那么国家这种模式呢需要大家呢呃常用常思考，他有他可以在代码上有不同的展现形式。
但是最关键的是什么？就是那个抽象的通知依赖关系啊，大家得把那个核心抓住。
呃，好，那我们今天的这个。
观察者摄影模式呢就谈到这里。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br><span class="line-number">177</span><br><span class="line-number">178</span><br><span class="line-number">179</span><br><span class="line-number">180</span><br><span class="line-number">181</span><br><span class="line-number">182</span><br><span class="line-number">183</span><br><span class="line-number">184</span><br><span class="line-number">185</span><br><span class="line-number">186</span><br><span class="line-number">187</span><br><span class="line-number">188</span><br><span class="line-number">189</span><br><span class="line-number">190</span><br><span class="line-number">191</span><br><span class="line-number">192</span><br><span class="line-number">193</span><br><span class="line-number">194</span><br><span class="line-number">195</span><br><span class="line-number">196</span><br><span class="line-number">197</span><br><span class="line-number">198</span><br><span class="line-number">199</span><br><span class="line-number">200</span><br><span class="line-number">201</span><br><span class="line-number">202</span><br><span class="line-number">203</span><br><span class="line-number">204</span><br><span class="line-number">205</span><br><span class="line-number">206</span><br><span class="line-number">207</span><br><span class="line-number">208</span><br><span class="line-number">209</span><br><span class="line-number">210</span><br><span class="line-number">211</span><br><span class="line-number">212</span><br><span class="line-number">213</span><br><span class="line-number">214</span><br><span class="line-number">215</span><br><span class="line-number">216</span><br><span class="line-number">217</span><br><span class="line-number">218</span><br><span class="line-number">219</span><br><span class="line-number">220</span><br><span class="line-number">221</span><br><span class="line-number">222</span><br><span class="line-number">223</span><br><span class="line-number">224</span><br><span class="line-number">225</span><br><span class="line-number">226</span><br><span class="line-number">227</span><br><span class="line-number">228</span><br><span class="line-number">229</span><br><span class="line-number">230</span><br><span class="line-number">231</span><br><span class="line-number">232</span><br><span class="line-number">233</span><br><span class="line-number">234</span><br><span class="line-number">235</span><br><span class="line-number">236</span><br><span class="line-number">237</span><br><span class="line-number">238</span><br><span class="line-number">239</span><br><span class="line-number">240</span><br><span class="line-number">241</span><br><span class="line-number">242</span><br><span class="line-number">243</span><br><span class="line-number">244</span><br><span class="line-number">245</span><br><span class="line-number">246</span><br><span class="line-number">247</span><br><span class="line-number">248</span><br><span class="line-number">249</span><br><span class="line-number">250</span><br><span class="line-number">251</span><br><span class="line-number">252</span><br><span class="line-number">253</span><br><span class="line-number">254</span><br><span class="line-number">255</span><br><span class="line-number">256</span><br><span class="line-number">257</span><br><span class="line-number">258</span><br><span class="line-number">259</span><br><span class="line-number">260</span><br><span class="line-number">261</span><br><span class="line-number">262</span><br><span class="line-number">263</span><br><span class="line-number">264</span><br><span class="line-number">265</span><br><span class="line-number">266</span><br><span class="line-number">267</span><br><span class="line-number">268</span><br><span class="line-number">269</span><br><span class="line-number">270</span><br><span class="line-number">271</span><br><span class="line-number">272</span><br><span class="line-number">273</span><br><span class="line-number">274</span><br><span class="line-number">275</span><br><span class="line-number">276</span><br><span class="line-number">277</span><br><span class="line-number">278</span><br><span class="line-number">279</span><br><span class="line-number">280</span><br><span class="line-number">281</span><br><span class="line-number">282</span><br><span class="line-number">283</span><br><span class="line-number">284</span><br><span class="line-number">285</span><br><span class="line-number">286</span><br><span class="line-number">287</span><br><span class="line-number">288</span><br><span class="line-number">289</span><br><span class="line-number">290</span><br><span class="line-number">291</span><br><span class="line-number">292</span><br><span class="line-number">293</span><br><span class="line-number">294</span><br><span class="line-number">295</span><br><span class="line-number">296</span><br><span class="line-number">297</span><br><span class="line-number">298</span><br><span class="line-number">299</span><br><span class="line-number">300</span><br><span class="line-number">301</span><br><span class="line-number">302</span><br><span class="line-number">303</span><br><span class="line-number">304</span><br><span class="line-number">305</span><br><span class="line-number">306</span><br><span class="line-number">307</span><br><span class="line-number">308</span><br><span class="line-number">309</span><br><span class="line-number">310</span><br><span class="line-number">311</span><br><span class="line-number">312</span><br><span class="line-number">313</span><br><span class="line-number">314</span><br><span class="line-number">315</span><br><span class="line-number">316</span><br><span class="line-number">317</span><br><span class="line-number">318</span><br><span class="line-number">319</span><br><span class="line-number">320</span><br><span class="line-number">321</span><br><span class="line-number">322</span><br><span class="line-number">323</span><br><span class="line-number">324</span><br><span class="line-number">325</span><br><span class="line-number">326</span><br><span class="line-number">327</span><br><span class="line-number">328</span><br><span class="line-number">329</span><br><span class="line-number">330</span><br><span class="line-number">331</span><br><span class="line-number">332</span><br><span class="line-number">333</span><br><span class="line-number">334</span><br><span class="line-number">335</span><br><span class="line-number">336</span><br><span class="line-number">337</span><br><span class="line-number">338</span><br><span class="line-number">339</span><br><span class="line-number">340</span><br><span class="line-number">341</span><br><span class="line-number">342</span><br><span class="line-number">343</span><br><span class="line-number">344</span><br><span class="line-number">345</span><br><span class="line-number">346</span><br><span class="line-number">347</span><br><span class="line-number">348</span><br><span class="line-number">349</span><br><span class="line-number">350</span><br><span class="line-number">351</span><br><span class="line-number">352</span><br><span class="line-number">353</span><br><span class="line-number">354</span><br><span class="line-number">355</span><br><span class="line-number">356</span><br><span class="line-number">357</span><br><span class="line-number">358</span><br><span class="line-number">359</span><br><span class="line-number">360</span><br><span class="line-number">361</span><br><span class="line-number">362</span><br><span class="line-number">363</span><br><span class="line-number">364</span><br><span class="line-number">365</span><br><span class="line-number">366</span><br><span class="line-number">367</span><br><span class="line-number">368</span><br><span class="line-number">369</span><br><span class="line-number">370</span><br><span class="line-number">371</span><br><span class="line-number">372</span><br><span class="line-number">373</span><br><span class="line-number">374</span><br><span class="line-number">375</span><br><span class="line-number">376</span><br><span class="line-number">377</span><br><span class="line-number">378</span><br><span class="line-number">379</span><br><span class="line-number">380</span><br><span class="line-number">381</span><br><span class="line-number">382</span><br><span class="line-number">383</span><br><span class="line-number">384</span><br><span class="line-number">385</span><br><span class="line-number">386</span><br><span class="line-number">387</span><br><span class="line-number">388</span><br><span class="line-number">389</span><br><span class="line-number">390</span><br><span class="line-number">391</span><br><span class="line-number">392</span><br><span class="line-number">393</span><br><span class="line-number">394</span><br><span class="line-number">395</span><br><span class="line-number">396</span><br><span class="line-number">397</span><br><span class="line-number">398</span><br><span class="line-number">399</span><br><span class="line-number">400</span><br><span class="line-number">401</span><br><span class="line-number">402</span><br><span class="line-number">403</span><br><span class="line-number">404</span><br><span class="line-number">405</span><br><span class="line-number">406</span><br><span class="line-number">407</span><br><span class="line-number">408</span><br><span class="line-number">409</span><br><span class="line-number">410</span><br><span class="line-number">411</span><br><span class="line-number">412</span><br><span class="line-number">413</span><br><span class="line-number">414</span><br><span class="line-number">415</span><br><span class="line-number">416</span><br><span class="line-number">417</span><br><span class="line-number">418</span><br><span class="line-number">419</span><br><span class="line-number">420</span><br><span class="line-number">421</span><br><span class="line-number">422</span><br><span class="line-number">423</span><br><span class="line-number">424</span><br><span class="line-number">425</span><br><span class="line-number">426</span><br><span class="line-number">427</span><br><span class="line-number">428</span><br><span class="line-number">429</span><br><span class="line-number">430</span><br><span class="line-number">431</span><br><span class="line-number">432</span><br><span class="line-number">433</span><br><span class="line-number">434</span><br><span class="line-number">435</span><br><span class="line-number">436</span><br><span class="line-number">437</span><br><span class="line-number">438</span><br><span class="line-number">439</span><br><span class="line-number">440</span><br><span class="line-number">441</span><br><span class="line-number">442</span><br><span class="line-number">443</span><br><span class="line-number">444</span><br><span class="line-number">445</span><br><span class="line-number">446</span><br><span class="line-number">447</span><br><span class="line-number">448</span><br><span class="line-number">449</span><br><span class="line-number">450</span><br><span class="line-number">451</span><br><span class="line-number">452</span><br><span class="line-number">453</span><br><span class="line-number">454</span><br><span class="line-number">455</span><br><span class="line-number">456</span><br><span class="line-number">457</span><br><span class="line-number">458</span><br><span class="line-number">459</span><br><span class="line-number">460</span><br><span class="line-number">461</span><br><span class="line-number">462</span><br><span class="line-number">463</span><br><span class="line-number">464</span><br><span class="line-number">465</span><br><span class="line-number">466</span><br><span class="line-number">467</span><br><span class="line-number">468</span><br><span class="line-number">469</span><br><span class="line-number">470</span><br><span class="line-number">471</span><br><span class="line-number">472</span><br></div></div><h2 id="_06-装饰模式"><a href="#_06-装饰模式" class="header-anchor">#</a> 06.装饰模式</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>嗯嗯。
好，那我们开始我们c加加设计模式的装饰模式啊，detail。
那装饰模式属于我们新的一个类别啊我们之前啊会把啊我们很多模式化为不同类别，我们来看一下我们这个类别属于我们叫单一职责模式，它讲的是在我们整个这个软件组件的设计过程中啊，如果责任划分不清晰，呃使用继承啊传统往往得到的结果是随着需求的变化呢子类会急剧的膨胀，同时会充斥很多重复代码。
这是两个我们一般叫做代码的bad，snow啊，代码的换位的呃。
诶这个时候的关键呢是划清责任。
当然了，就像我们其他的模式一样的道理，我们说这两个模式呢，dragon的模式和breaking模式呢，他把我们把它划到单一职责模式里边，是他们在责任的问题上表现得特别突出。
但这不意味着其他模式没有责任问题啊，只是说这两个模式在责任上表现得极其突出，特征非常明显啊。
好，我们直接来看我们这个加快的模式。
呃那我们刚才讲就是过度的使用继承来扩展对象功能会出问题啊，当然我们还是要存在嘛，对吧？
收musical的啊。
呃首先呢我们这一个设计场景啊是我们在设计一个嗯i。
兜的库啊，就是一些流操作啊。
那针对流操作呢，我们首先是啊我们有很多流的需求，比如说我们有文件流、有网络流、有内存流啊等等。
那我们也有一些比如说对流进行加密啊，对引流进行一些这个嗯缓存啊等等各种各样的操作啊所以这个时候呢我们首先会想到哎流的设计呢可能我们很快就提出来哦那是需要有一个鸡肋，对吧？
这个这个鸡肋呢我们呃说哎那有呃比如说像red、像secret、像red这样一些公共操作，我们作为纯虚函数放到这样一个啊steam鸡肋里面。
ok。
然后呢我们再来看文件流文件流的设计，当然我们说哎我们去继承它，然后呢我们去oled这样一些啊函数。
就去读文件啊、定位文件流、写文件流等等。
网络流其实做法也是类似啊network spring啊，然后继承它，然后就偶尔的这些血函数啊到内存流也是这样这样的做法。
然后我们再来看，当我们要去考虑加密啊的操作的时候，我们就会发现我们需要对流程首先有一个主体的操作，我们才能加密。
我们很难说就是一个硫直接进行加密。
我们比如说我们这里面就考虑出来加密文件，我们要对文件流进行加密。
它的编写方法是这样的，我们首先去继承这个文件，然后呢我们在它上面呢这个red这个read上面去做一些额外的操作。
所以大家看六十行，六十行是调用鸡肋啊，这个鸡肋就是feel。
of，string。
那然后呢我们在它上面呢去做一些这样的一些额外的加密操作，当然这个可能放在前面，可能放在后边啊，无所谓你放在哪里啊，只是我们在这里呢我们说我们是用一个维码的表示啊啊那你你也可能放在这里啊也可能放在这里啊。
ok。
然后c课比如说c课呢我们也会出现这样的问题啊，我们比如在在六十六行这个c课之前呢，我们可能需要做一些额外的加密工作，可能在之后呢也需要做一些额外的加密工作。
然后read一样的，我们也是在前后都要做一些加密操作。
嗯当我们这样写下来之后啊，我们再去考虑，比如说你对文件流进行加密操作，那你对网络流有没有加密的需求呢？
也有。
capital啊，network，student。
样的类似啊，其实大家会发现加密的操作都是一样的，只是什么你的这个流的读取的操作是不一样的，对吧？
比如说这个网络柳啊，这个操作和内存啊和文件流这个操作不一样，但是呢你的其他的加密操作都是一样的。
这边也是我们针对▁ra，id有它的加密操作，针对set也有它的前后的加密操作，针对rate也有前后的加密操作。
然后我们再来看内存流，呃我们一样也要对内存流进行加密操作，对吧？
我们也是啊非常类似的代码啊，当然我们写到这里，我们再来看，比如说呃同同样的道理也都会，比如说我要做buffer啊，要做缓冲，对吧？
呃流的缓冲处理的话我也要考虑就是我对文件流进行缓冲，我对网络流进行缓冲，我对内存流进行缓冲，啊这里我就不写具体的这个这个设计的表示了。
大家可以根据上面这个加密的操作也推断这样的一个设计。
呃当然再往后呢我们可能还有什么我针对文件流进行既加密又缓冲这样一个双重的操扩展操作，对吧？
那么比如说question，of the file stream，去继承一个file stream。
当然有的朋友可能也会在这里面就直接去继承一个什么呃继承一个cover、talk、fire，spring也也可以啊也可以，然后呢在这里面进行额外的加密操作、额外的缓冲操作，然后再去做真正的读取文件流的操作一样的，这个也是额外的加密操作、额外的缓冲操作啊等等。
那这样做下来啊，我们现在来看一下这个设计有没有问题啊。
呃当然我还是给大家做了一些埋伏，对吧？
呃问这个问题的时候，大家听过我们。
前面的课就知道他的设计是有问题。
那现在就是大家一起来看看有什么问题来思考呀。
如果你做出来这样的一个设计，它带来的毛病是什么？
呃当然有些朋友告诉我，李老师，我上去就可能能做对，我上去就不一定是按照你你故意给我设计的这个陷阱来去设计的。
我告诉大家啊，很难啊，就说没有学过咱们dark cat设计模式的朋友呢，绝大多数情况下是很难做到一步做出正确的设计，而且绝大多数情况都会掉入这个陷阱里，就是你会沿着这个继承的路子往下走。
好，那我们来看一下这里面。
大家刚才思考了一下啊，就是有什么问题呢？
我做一个梳理。
我在这里呢打开我们另外呃一段这个这个slice我们来看一下我们另外一段slice是这个嗯咱们一起来看一下。
刚才这个设计里边呢哎整理一下啊整理下我们的设计的这样整个类图的结构啊。
stream是在最顶上的，对吧？
鸡肋。
然后我们分别做了三个类型，feel，studio继承steam，network，structure继承stream，merry，streaming，继承stream。
啊然后再对他们的操作啊，就是那些red，secret分别进行了一些自己的or red的版本，重写的版本，对吧？
然后接着呢我们加有加密文件流，有加密网络流，有加密内存流，有八份的文件流，八份的网络流。
buffer的内存流，对吧？
我们还有capital buffer的那文件流，又有certain，of buffer的网络流，又有capital buffer的内存流。
大家想一下这个类的规模有多少啊？
stream就是数量啊，类的数量有多少？
stream我们假设是一，对吧？
就是一。
然后我们再说第二层，就file，student，work，special，manager这一层呢我们假设比如说它的变化个数有n个，那就是一加n，对吧？
然后再往下呢，咱们假设这个加密对文件流进行加密，对文件流进行缓存，对文件流进行各种各样的操作。
整个这个下来呢呃我们说假设有m种操作，大家想想这个加起来是个数是多少？
一加n在家什么也。
嗯可能会讲的是m乘n，对吧？
我告诉他不是m乘n啊注意他们有组合的情况，我可以既加密又缓存。
所以你算下来实际上是那个n乘以什么m括弧，m加m减一，加m减二，一直加到一。
其实就是在数学上是最后出来是一个数，m的阶乘m的阶乘除以r，对吧？
就是它整个数数据的规模最后出来是一加n加n乘以m的阶乘除以二。
哦这个规模是不得了的，非常之大，对吧？
大家算一下，我们这个才什么上面n是三，m是二，大家算下来是多少？
一加啊。
三加上什么？
底下是三乘以三，是吧？
九啊就。
加三加一是吧？
十三个是吧啊那么如果你这个n是五，m是六呢，哇那个不得了，那个算出来几十个甚至上百个啊呃那什么问题呢对吧就说什么问题导致了这个刮痧出来这么多泪，但是不要紧啊。
大家再来看一下，这个类的个数增多的同时，它的背后还有一个，如果大家打量这个细节的话，你会发现出来这样一个问题。
我们来看加密文件流五十九行这个地方啊和加密网络流和七十九行再和九十八行，这个其实是一样的，都是对red的一个加密操作。
对吧？
五十九行不合？
呃七十九行，以及我们说九十八行，不会因为你这个red的不同而不一样，你的red六十行的red，对吧？
你非要steam的red和你network spring的red出来的东西，我针对你进行加密的时候是一样的加密操作。
所以大家如果真正去写代码的时候，你会发现这里面有代码冗余，就是代码是一模一样的，五十九行、七十九行、九十八行，对吧？
那一样的啊。
然后你再看ck底下的加密操作，也会发现他们也是一样的，然后你再去看red的底下，也会发现他们也是一样。
那我们说了一样的代码，大家如果看那个马丁福勒那本重构的啊，非常经典的一本书，reveal，person。
啊就是我们之前给大家在设计模式之前推荐的一本书啊你看重构的话你就能看出来这些问题，对吧？
这就是什么典型的bad，summer代码，在大量的被重复，呃重复就要消除重复，对吧消除重复，我们来看看我们用什么办法。
这就是我们现在重构就有找着呃点对吧找到具体的重构点。
好，重构的时候呢我们为了便于大家课后的复习啊，我们这里呢把这个代码呢做一个啊做一个复制。
啊然后呢我们写成二，再cut二，我们在第二个版本上去去对它进行重构啊。
好，大家想一下，我们这个怎么重构呢？
因为现在已经找到重复点了，对吧？
queue，profile，spring和capital，note，stream以及cooperate。
management。
重复的。
大家想一下这个呢他们的不一样在哪在哪里？
也就六十行和八十行。
但是六十行和八十行是完全不一样吗？
其实也不是，只是一点点不一样，对吧？
他们实际上red的规范都是一样的。
所以这里边大家想一下啊，它是file，stream。
假设我现在啊把这个东西注意看啊，瞪大眼睛看啊，这个时候一定要我们把这个继承扔下来，放到这里。
好，假设我这儿继承放了一个放成了一个字段，stream这样一个字段。
注意啊，大家仔细看啊，然后呢我。
把network stream这里啊，刚才那边多放了一个冒号，是吧？
好，这个地方呢我也放成一个一个的字段。
好，那这个地方呢merry，stream这个地方呢我也把它移下来。
这这个其实呃如果学过咱们之前的设计原则的时候，我们知道设计原则有一句话叫做什么profile组合图集成，是吧？
就是就是更更倾向于或者我们用简简单化叫组合优于继承。
我们现在用组合替代了刚才的继承人。
然后再来看，我把这个stream我在这儿换掉，有没有大的问题啊？
没有大的问题，对吧？
它是feel。
spring，one，对不对？
我我从从父类去去呃去调用fifa stream和从无一个字段调用file stream效果是一样的啊。
有些朋友不还不理解这一点，仔细回想c加加以前的基础啊，鸡肋和组合，一个子呃呃这一个一个一个鸡肋的呃对象类型，其实你在这里面调的效果是一样的。
好，再来把这个地方换下来。
再来把这个地方也换下来。
好当一换到这里，有过多态训练，有过多态意识的朋友慢慢就意识到了。
哇越来越像像了，是吧？
越来越接近了啊再看五十七行和。
七十九行这个地方是不是极其接近啊？
和一百行它们的差别仅在于什么？
你想想，咱们咱们在重构里面，其实啊呃重构这本书里面也有一条规则，当一个变量你的类型、你的声明类型都是你某个类型的子类的时候，你就应该把它声明成某个类型就行了，就不要声明他此累了。
你想想这里我们就声明成stream，因为它是多肽嘛，我未来让它成为这个可以吧？
我是讲未来，所谓未来就是运行时，注意啊，我强调这个round，time这个关键词啊，我把编译时的东西变成了运行时的东西。
好，接着再来这里看这个这个变化非常。
非常有意思啊，这真是大家理解了这一段，你就会发现继承和组合之间的奥妙之处啊。
我也是把这个network streaming换成了spring，然后呢等于new network studio是吧？
好，继续再往下。
对到这里，牛奶。
minecraft，spring。
好，大家来看啊，注意，当我写到这里的时候，是不是很多人朋友恍然大悟了？
哇这三个人一样了，是吧？
对啊，我是想这里面一样的，他们的不一样在哪里？
不一样在咱们柱石的那个未来，就是运行时让他们不。
一样，编译是让他们一样，这就是咱们设计和绝大多数设计模式的真谛，就是编译是让他共用复用，它的变化它的需求的变化都给它扔到运行时，用多态的方式来让它支持它的变化。
所以你就会看到steam这里的stream和这里是全都一样了，对吧？
那将来就是说你将来new出来的是file stream，那你六十三行这里就是fire，stream，你将来是network streaming，那六十三行就是network string，你将来是merry stream，你这样这里面六十三行就是merry stream。
商品。
那一旦这样做了之后，你就会发现这三类一模一样，只是名字不一样。
那你还干嘛还要这仨类？
就一个类就可以了，对不对？
就合并了嘛。
合并就是什么就是消除了马丁弗勒讲的重复性，是吧？
代码层面的重复性。
好，我们把这个少取掉，当我们消除掉之后啊，当然这个地方咱们都给他换过来啊。
啊都给他换过来。
然后这个地方就是我就用个省略号，好吧？
省略号就表示未来有各种各样的stream可以塞到这里来支持我的变化，对吧？
同样的道理啊，八分的steam也没有必要这么多了是吧？
一个就可一个就可以了，而且不需要是针对菲奥斯贝姆啊。
那这里你就遗留了一个问题啊，就你这样写了之后呢，你这个凭什么是虚函数啊？
六十行篇目是信息函数，六十五行匹配什么是序函数？
那你还是要遵循呃流的规范，你才能是虚函数，对吧？
你才能。
所以这里面还要去把这个再加上一个鸡肋。
注意啊，有些人朋友这个地方会犯迷糊啊，会会会会晕。
就为什么这儿要要要要加上这样一个鸡肋呢？
啊这个积累是为了完善这个虚函数六十行的虚函数六十五行虚函数、七十行的虚函数的这样一个接口规范的啊，也就是stream这个积累定义了为copy的flash，a stream定义了鸡肋的接口规范啊。
当然这个地方没有必要写feel了对吧？
paper，study，注意啊，这里面发生了非常奇妙的一个。
变化，就是它既有一个stem积累，又有一个stream的字段啊当然你继续做下去buff的steam，你会发现也会呈现这样的一个特征，具体设计我就不写了啊，它也应该是这样的一个特征。
好。
那当然当咱们写到这里的话啊，其实呢这个问题已经得到极大的缓解了啊极大的缓解。
那么呃真正去使用的时候呢我们真正去用的时候啊，我我们也给大家刚才看刚才刚才的用法是什么啊刚才如果你设计出来了的话，你是certainly。
feel，station，对吧？
创建啊buffer的。
feel。
streaming。
啊。
copy，to，the。
birthday。
fire。
stream。
我们那我们叫把。
那个叫做装配式编译。
如果我们像刚才这样做了之后呢，我们就发现呢这些装配式编译我们可以可以给它改成下面的版本，怎么什么样的版本呢？
比如说fire，spring，啊f。
s等于new，let's go，对吧？
然后呢啊capital，spring，f，s二。
我就写成s一吧，然后s二等于new。
apple。
spring，然后呢括弧再传递▁x一。
呃注意啊这个地方当你写下这个字段的时候，你是不是将来要创建一个构造器，对吧？
你其实是要有一个构造器的啊。
呃然后呢我我这个就把这个构造器写上吧，然后spring。
是不是要这样写，对吧？
然后呢当然你这边就就直接这样的一个成员初始化列表方式啊就可以了。
当然嗯如果你你想刻意的去把它们区分开来的话，也可以稍微的做一下这个。
呃里边起个不一样的名字啊，都都可以。
s。
tm吧。
假设是这样。
啊就是给它整一个构造器，那么你这个构造器就是需要这样传递，是吧？
啊那当然你这个八分的beyond，stream就可以怎么样子啊？
比如说八份儿的。
然后s三等于new buffer的spring，然后s一传进去，它就是针对啊文件流的进行一个buffer。
如果是我既加密又缓存呢，那是不是我就是这样一个东西？
offer的s四等于new八份儿的，像括弧啊，然后把这个s二传进去，是吧？
这个就是既加密又缓存，那我。
这样子啊用下来啊。
我们把前面就删掉啊。
这个叫什么？
这个叫运行时装配。
就是我编译时我不存在那些什么我这呃加密文件流、缓存文件流或者加密缓存文件流，对吧？
我没有那样的累，但我运行时可以通过组合的方式把它们装配起来，然后呢满足我的需求，对不对啊当然这里边啊你这样这这个类啊这个类就没必要了，对吧？
这个这个类是刚才还是第一个版本的时候遗留下来的东西，我们现在就很干净了啊，只有这几个。
就这几个啊当然这个地方也是需要有一个构造器，是吧？
对，然后把这个天呃buffer的spring放到这里就可以了啊。
其实到这里这个问题已经解决差不多了啊已经解决差不多。
当然这里面如果根据马丁福特经典意义上的重构理论呢，存货里面还有一条叫做什么？
如果某一个类它的它有两个子类啊或者多个子类都有同样的字段的时候，应该把这个往上提啊。
榜上题提到哪里呢？
比如说大家看巴菲特，steam有同样八十六行这个字段，streaming字段，corpories，beam也有这个字段，对吧？
那这个时候提呢有两种提法，第一呢是把它提到鸡肋里，提到呃这个这个spring彻底讲到这里，但大家想提到这里会带来一个什么影响？
inform。
student需不需要这个字段？
当然不需要。
对哈。
files任务它是一个主体上说他不需要那个那个steam的这个字段，它就可以完成它文件流的操作。
所以你提到这里不合适。
那应这个时候应该怎么做呢？
其实应该设计一个中间类啊中间类这个中间类是什么？
你你可以写个名字啊，其实就是我们的double reit。
string，继承。
public，spring。
啊我直接设计这样的一个一个中间积累啊，这样吧为了便于大家这个后边的复习啊，我也是把这个文件也单独的给它抠出来。
号称第三个版本，其实第二个版本在很多类库里面挺常见的啊就是以那样做其实已经ok了，但是呢。
有的有的这个比较完美啊，或者是比较这个更加这个规范的实现呢，就是在我们这里，我把这个先拿掉啊。
就是这里再放再放一层中间的这个这个装饰类啊中间的装饰类就是把这个往上提。
当然因为这样子，所以需要把它生成protect，是吧？
啊然后呢这个database stream呢？
诶sorry，放到这里对吧？
然后呢当然这个就是调用鸡肋的构造器了，对吧？
所以这里也是啊也是继承积累detail的spring，然后调用机类的构造器。
那你这个鸡肋是不是也要再单独写一个过道器？
然后这个构造器嗯那位写成其实写成pet ct的也ok啦。
然后呢spring。
啊然后呢这个string，s，tm。
好，这样就ok了，对吧？
呃这样梳理下来啊，大家就会发现是不是很很巧妙？
很会很奇妙啊？
对，我们再来看一下这个关系图啊，看下类关系图，你又会发现这个巧妙在哪里？
我们现在拥有了哪些类啊大家看，文件流在这个文件流、网络流、内存流在这里面始终没动啊他们是可以单独行驶。
行。
末尾的，对吧？
单独我创建一个单独的file。
stream是可以单独用的啊，我可以拿来files，就是我不做加密的操作总可以吧？
但是呢加密呃轮流呢你必须什么传一个流流的对象，第一传一个比如说s、e粉文件流，对吧？
或者八份，你必须传也传一个secret。
因为我们说这些操作呢本质上它是扩展操作，扩展操作就是你在谁的基础上再去做，这就是装饰determat这个英文的含义啊，这装饰是附着在其他地上，放呃上上面的一个一个一个操作，对吧？
这就叫装装饰操作。
好，有了这样一个认识之后，咱们来看这个slice，我们把前一幅图啊，我们说不。
好，让我们改通过我们的重构改造成了厚衣服。
大家来看这幅图，这幅图streaming，不变，file，stream，and works，rock，stream，merry，student仍然不变。
然后那我们设计了什么？
day，quarter，stream，color，string，即成dark。
talks怎么样？
巴菲特。
steam继承dark。
test。
那大家再来看这个之间的关系是什么呀？
就类的总数啊，类的规模。
一加，左边是n，右边是m的话是什么？
一加n加一加m是一个家的关系，而前面是一个什么是一个阶乘之后成的关系，是吧？
这个一加我在这儿。
呃这个这个简简单简单写一下啊对，简单写一下。
这个这个数这个数量啊整个这个数量是。
一加n加n乘以m的阶乘除以二，是吧？
哇这个这个规模是超级超级大的啊。
对，我把它放大一点啊，用红色表示吧。
然后咱们再来说这个，这个呢就一加n加一加m，大家数学应该都不错啊，功底都不错，你记你可以去算一下这个这这这这算下来差别太大了，对吧？
呃如果n是就是我说n是五，m是六的话，划你算出来这是十几倍的增长啊，非常厉害。
但原因是什么原因是你背后的很多重复代码啊是由于对继承的不良使用。
再回顾一下啊，我这句话对继承的不良使用，就是我们之前是在疯狂的用继承，对吧？
咱们再再来看一下啊，这个大家有没有看这个是这个下面都在继承他，对吧？
但是我们想一想我们现在再想一想，到底这个quarter，feel，string，buffer的file stream是不是一定要去继承file stream来完成他的加密和缓存操作呢？
不是的，我们发现组合更好，大家注意啊，这里边实际上这个critical stream或者data spring里边有一个指针，对吧有一个指针啊指向了fine或者是fire，stream，或者是network student，或者是number three啊这个指针是非常妙的。
好没有？
再来，就这里啊，五十九行。
这个指针这个指针是咱们整个设计的核心啊，就是用组合的方式来引出一种多态的这个这个支持啊支持未来的多态的变化。
好，那我想谈到这里啊，大家应该对我们这个带宽模式已经有有一个不错的感觉啊，我们现在呢回来回到我们ppt上做一个总结。
嗯咱们刚才说的动机是什么呢？
就是在某些情况下，我们可能会过度的使用继承来扩展对象的功能，由于继承为类型引入的静态特质，注意这句话有些人不太理解，我再退回到代码。
啊来看一下什么叫为继承为类型引入的静态特质啊。
来看这个这个地方就是静态特质，六十行是没有什么变化的可能性的，六十行定死了，永远是调用flag，streaming的red，对吧？
然后这个八十行也是定死了，永远是掉network streaming的red。
而我们通过这样的一种方式。
这个地方就是有变化的，对吧？
就是一个一个指针啊一个指针啊一个多态的指针，stream是一个一个一个鸡肋的呃指针啊这样一个多态指针调用它的虚函数，那它就有变化了啊所以所以我们把八。
这行叫做静态特质，把七十九行叫做动态特质。
啊那八十行是由什么由继承实现的，而七十九行是由组合实现。
啊对，把握住这一点啊，就是我们讲的理论其实都是应该映射到代码上啊映射不到代码上的。
在软件开发领域的理论不叫理论啊。
好，那我们说静态特征使得这种扩展方式缺乏灵活性，并且呢随着子类的增多啊，就是你扩展功能的增多，各种子类的组合情况啊会导致子类急剧膨胀啊就是我们刚才说的那个那那个数量，对吧？
你算一下会会吓吓晕你的啊如果你在一个真正的项目里面敢这么干的话啊那那那这个可维护性。
会会会超会很快会让整个团队崩溃掉。
那如何解决呢？
我们来看一下g、o、f对这个模式的定义啊，动态的给一个对象增加职责啊注意我我括弧里边啊是我加的一个注解注释啊，就是我们的组合手段，对吧？
哎就增加功能而言，daddy的模式已生成子类，就是继承的方式，对吧？
就是组合优于继承的典型体现，更为灵活。
所谓更为灵活就是在我们这儿达到两个目标，第一，消除重复重复代码；
第二，减少子类个数。
好，然后我们来看一下这个结构啊，那我先圈一圈勾一下啊。
那么大家来看这个component相当于咱们的什么string类型，是吧？
鸡肋。
database类呢相当于咱们的data。
streaming啊我还是用红蓝笔啊，红色表示什么咱们稳定的部分，蓝色表示变化的部分啊就是你看设计模式的图一定要能看出来这个红色和那就是呃稳定的部分和变化的部分。
康辉的company，它是咱们的变化的部分，对吧？
是feel，stream啊，network，streaming，number，three这些变体。
然后这个computer，darker，a，computer data，b是咱们的什么呃critical spring呢，buffer的speaker啊是是是另外一个部分的变体。
好，那我们来做一个总结啊。
通过采用助组合而非继承的手法，带宽的模式，实现了在运行时动态的扩。
展对象功能的能力。
注意我们这儿有几个关键词啊，运行啊，一定要理解这些关键词啊，这设计模式这些这些关键词啊其实呃在咱们这里边啊非非常非常非常重要啊。
呃我们我还是比较啊对喜欢这个这个红色来画，而且可以根据需要来扩展功能，避免了使用继承带来的灵活性差和多子类衍生问题。
那待会就▁ed，it or类呢？
在接口上表现是什么？
一个a是恶的关系，就是说它既继承stream，同时又组合stream，但在实现上又表现为孩子恶的关系，这个非常精妙啊，这是。
埃克特模式非常独特的一个特点，甚至可以这样说啊，大家我们先找到这个代码。
呃我们可以这样讲，就是今后大家啊以后在你这个设计生涯里面啊就是面向对象设计生涯里面，你如果看到一个类，他的父类是一个类啊父类是stream，它里面又有一个字段，又是stream，就是同一个类。
这个类就是你就高度怀疑他是david的设计模式。
以我的经验，百分之九十九的情况都是啊。
为什么？
因为正常的情况不会这么干，对吧？
正常情况你我们一般说你要么继承一个类就完了，要么你组合一个类就完了，你很少需要什么同时继承，同时又组合，是吧？
这么玩儿的一定有特别独特的一个设计含义啊。
嗯因为一般意义上我们讲继承和组合，对吧？
你你你继承了你就不组合了，组合就不继承了。
他两个在那次模型上，很多时候甚至在设计的功能上都是有一些类似的地方啊。
但是我们这里特别特殊，我们这里啊这个继承这个stream是干什么？
为了完善接口的规范，就是这里定义的接口，对吧？
而我们这里的组合这个stream是为了什么是为了将来支持实现的，支持调用fire，spring，network，string，merry，stream这些具体的实现类的啊，这两个继承和组合是完全不一样。
嗯所以这是这是double的模式的一个重点，也是一个特特点。
当然有的时候。
你可能在一些时间上你看不到人家的内部字段，但你至少可以通过什么通过这个类的外部接口可以看。
一个类的外部接口什么会告诉你呢？
就是它的父类是某一个类，它的构造器的参数又是同样一个类型。
啊你也会从这个推断出来它很像带亏的模式。
好，我们再回到我们自来。
就是刚才讲那最后我们讲darker的模式啊，它也不是说只要多子类延伸啊这个这个延伸的多继承问题啊，代课的模式，这个应用的要点在于解决什么主体类的多个方向上的扩展功能。
就咱们再回到刚才那个词，来像在再来对比，你看一下啊这个。
大家想一想啊，拿着这张slice仔细回顾一下，就这这个东西之间的真的是继承关系吗？
非要steam和stream是继承关系，但critical呃这个spring哦和fire spring一定要继承吗？
不是的，对吧？
你会发现他两个根本就我们叫不是一个变化的方向，这是file，stream，native，spring，marry，marry，stream，这是一个变化的方向。
但是corp托f，ore，stream啊这真的不是一个变化的方向。
实际上他们是扩展操作啊，他们是国产操作，而facebook是主体操作主体的操作和扩展操作应该分开，分支继承啊。
就像我们第二设计方式，这这个这个darker的模式其实可以带给大家非常多的思考啊，就有关组合和继承的非常多。
好，那我们今天的这个课程就就到这里啊，大家回去我建议好好把我们的这个代码研读一下啊，你你用还原我们刚才的重构的场景，仔细思考为什么要重构？
为什么用这种方法重构？
实际上有些朋友可以试试别的方法重构啊，我自己试过了，因为课程时间的关系，我不能把所有的尝试都交给大家，但你尝试多种尝试之后，你发现结果真的最完美的结果还是我们今天讲的这个结论啊所以你会是吧？
就是我我们之前说你读那个设计模式这本书啊，就是我们这这四位大师，对吧？
gui、gui、google graphy、g、o、f，这这这四个大师写的书，你就有一种呃捶捶胸顿足的感觉啊就是啊大师还是大师是吧？
就是他能把你在设计上遇到的困惑，以一种特别优雅的方。
给到你啊当然我们说他们也是总结了很多前人的经验啊。
好，那我们今天课程就到这里啊，谢谢大家。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br><span class="line-number">177</span><br><span class="line-number">178</span><br><span class="line-number">179</span><br><span class="line-number">180</span><br><span class="line-number">181</span><br><span class="line-number">182</span><br><span class="line-number">183</span><br><span class="line-number">184</span><br><span class="line-number">185</span><br><span class="line-number">186</span><br><span class="line-number">187</span><br><span class="line-number">188</span><br><span class="line-number">189</span><br><span class="line-number">190</span><br><span class="line-number">191</span><br><span class="line-number">192</span><br><span class="line-number">193</span><br><span class="line-number">194</span><br><span class="line-number">195</span><br><span class="line-number">196</span><br><span class="line-number">197</span><br><span class="line-number">198</span><br><span class="line-number">199</span><br><span class="line-number">200</span><br><span class="line-number">201</span><br><span class="line-number">202</span><br><span class="line-number">203</span><br><span class="line-number">204</span><br><span class="line-number">205</span><br><span class="line-number">206</span><br><span class="line-number">207</span><br><span class="line-number">208</span><br><span class="line-number">209</span><br><span class="line-number">210</span><br><span class="line-number">211</span><br><span class="line-number">212</span><br><span class="line-number">213</span><br><span class="line-number">214</span><br><span class="line-number">215</span><br><span class="line-number">216</span><br><span class="line-number">217</span><br><span class="line-number">218</span><br><span class="line-number">219</span><br><span class="line-number">220</span><br><span class="line-number">221</span><br><span class="line-number">222</span><br><span class="line-number">223</span><br><span class="line-number">224</span><br><span class="line-number">225</span><br><span class="line-number">226</span><br><span class="line-number">227</span><br><span class="line-number">228</span><br><span class="line-number">229</span><br><span class="line-number">230</span><br><span class="line-number">231</span><br><span class="line-number">232</span><br><span class="line-number">233</span><br><span class="line-number">234</span><br><span class="line-number">235</span><br><span class="line-number">236</span><br><span class="line-number">237</span><br><span class="line-number">238</span><br><span class="line-number">239</span><br><span class="line-number">240</span><br><span class="line-number">241</span><br><span class="line-number">242</span><br><span class="line-number">243</span><br><span class="line-number">244</span><br><span class="line-number">245</span><br><span class="line-number">246</span><br><span class="line-number">247</span><br><span class="line-number">248</span><br><span class="line-number">249</span><br><span class="line-number">250</span><br><span class="line-number">251</span><br><span class="line-number">252</span><br><span class="line-number">253</span><br><span class="line-number">254</span><br><span class="line-number">255</span><br><span class="line-number">256</span><br><span class="line-number">257</span><br><span class="line-number">258</span><br><span class="line-number">259</span><br><span class="line-number">260</span><br><span class="line-number">261</span><br><span class="line-number">262</span><br><span class="line-number">263</span><br><span class="line-number">264</span><br><span class="line-number">265</span><br><span class="line-number">266</span><br><span class="line-number">267</span><br><span class="line-number">268</span><br><span class="line-number">269</span><br><span class="line-number">270</span><br><span class="line-number">271</span><br><span class="line-number">272</span><br><span class="line-number">273</span><br><span class="line-number">274</span><br><span class="line-number">275</span><br><span class="line-number">276</span><br><span class="line-number">277</span><br><span class="line-number">278</span><br><span class="line-number">279</span><br><span class="line-number">280</span><br><span class="line-number">281</span><br><span class="line-number">282</span><br><span class="line-number">283</span><br><span class="line-number">284</span><br><span class="line-number">285</span><br><span class="line-number">286</span><br><span class="line-number">287</span><br><span class="line-number">288</span><br><span class="line-number">289</span><br><span class="line-number">290</span><br><span class="line-number">291</span><br><span class="line-number">292</span><br><span class="line-number">293</span><br><span class="line-number">294</span><br><span class="line-number">295</span><br><span class="line-number">296</span><br><span class="line-number">297</span><br><span class="line-number">298</span><br><span class="line-number">299</span><br><span class="line-number">300</span><br><span class="line-number">301</span><br><span class="line-number">302</span><br><span class="line-number">303</span><br><span class="line-number">304</span><br><span class="line-number">305</span><br><span class="line-number">306</span><br><span class="line-number">307</span><br><span class="line-number">308</span><br><span class="line-number">309</span><br><span class="line-number">310</span><br><span class="line-number">311</span><br><span class="line-number">312</span><br><span class="line-number">313</span><br><span class="line-number">314</span><br><span class="line-number">315</span><br><span class="line-number">316</span><br><span class="line-number">317</span><br><span class="line-number">318</span><br><span class="line-number">319</span><br><span class="line-number">320</span><br><span class="line-number">321</span><br><span class="line-number">322</span><br><span class="line-number">323</span><br><span class="line-number">324</span><br><span class="line-number">325</span><br><span class="line-number">326</span><br><span class="line-number">327</span><br><span class="line-number">328</span><br><span class="line-number">329</span><br><span class="line-number">330</span><br><span class="line-number">331</span><br><span class="line-number">332</span><br><span class="line-number">333</span><br><span class="line-number">334</span><br><span class="line-number">335</span><br><span class="line-number">336</span><br><span class="line-number">337</span><br><span class="line-number">338</span><br><span class="line-number">339</span><br><span class="line-number">340</span><br><span class="line-number">341</span><br><span class="line-number">342</span><br><span class="line-number">343</span><br><span class="line-number">344</span><br><span class="line-number">345</span><br><span class="line-number">346</span><br><span class="line-number">347</span><br><span class="line-number">348</span><br><span class="line-number">349</span><br><span class="line-number">350</span><br><span class="line-number">351</span><br><span class="line-number">352</span><br><span class="line-number">353</span><br><span class="line-number">354</span><br><span class="line-number">355</span><br><span class="line-number">356</span><br><span class="line-number">357</span><br><span class="line-number">358</span><br><span class="line-number">359</span><br><span class="line-number">360</span><br><span class="line-number">361</span><br><span class="line-number">362</span><br><span class="line-number">363</span><br><span class="line-number">364</span><br><span class="line-number">365</span><br><span class="line-number">366</span><br><span class="line-number">367</span><br></div></div><h2 id="_07-桥模式"><a href="#_07-桥模式" class="header-anchor">#</a> 07.桥模式</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>一、二、三四五、六、七。
好，那我们开始我们这家设计模式啊，bridge桥模式的讲解。
呃桥模式呢也属于我们一个典型的单一职责模式啊他跟我们上节课讲的呆哭的模式的很多特征实际上非常类似啊但也有些不一样的地方啊，它主要的特征都是我们讲的子类急剧膨胀，充斥重复代码啊，这个时候划清责任非常重要。
好，我们来看一下，乔布斯主要解决的问题的动机呢是啊由于某些类型具有一些固有的视线逻辑，使得他们有多个变化的维度。
那么这个话的理解呢还是要回到代码上啊，大家首先来看一下。
我们这里面假设我们有这样一个message的设计，呃这是一个呃通信啊通信的一个一个一个简单的一个这样一个模块儿啊。
这个message呢需要处理用户的有loging，叫science，message叫seven，pixel。
同时呢我们还要考虑一些问题，比如说它可以播放声音，它可以在呃就是它具体在品牌实现层面啊，它可以在呃界面上画一些图形啊，展示一些图像啊，或者是一些呃在某些这个端口上写入一些呃这个数据，包括连接网络等等。
啊。
对，如果我们刚开始设计的话，我们可能会想到哦这个message有各种各样的功能啊，需要你去实现它。
呃当然仅。
接着呢我们就会想到哎呦我们呃假设我们要支持pc的平台的设计，也要支持某表平台的设计啊那么这个时候呢就需要设计比如pc message，base啊，我去继承这个message。
我们为什么说它是pc message呢？
我们发现当我们去写pc message和moba message，我们都会发现一个尴尬的地方，就说我们主要是因为这个地方的不同，就是平台实现，比如play上的pc平台和这个这个moba平台，我们说播放声音的时候是不一样的啊它的实现方式是不一样。
比如说在在界面上画一些图形，job，ship的时候也是不一样，然后在这个端口里面去写入一些啊数据啊也是不一样，然后连接网络的时候也是不一样。
所以呢这个时候呢。
我们看我们pc mac者去override这几个函数，那么模板master也是去override这几个函数。
啊当我这里面都有不同的这种这种这种主食的方式来表达他们是不同的实现。
呃当然很快，我们同时我们会发现我们需要支持什么不同呃在不同平台上呢我们需要支持不同的功能啊比如说我们要推出这个经典版，我们也要推出一个完美版啊那比如说这个时候呢我们就要考虑在pc平台上，比如我们有一个pc，message，the light继承pc message，the base。
那我们就要这个时候是是实际上是实现某些函数啊，比如说loging啊，sanna，message，sunny，package，这些函数的实现的时候呢，我们比如说像。
要联网，loading的时候需要联网，然后需要保持一些网络状态，然后send，message都需要在网络端口上写数据。
然后science，package呢需要在网络端口上去发送一些数据的图嗯图像的一些转成的一些数据包啊等等这样的一种方式啊，注意都是在调用机内啊。
pc。
matthew，bitch，please，master。
base啊等等。
然后呢再来看b、c，g，method，profite也是一样的，就是我们这个当然功能变多了，但是你的基本的东西是不变的，对吧？
那么你你同样你需要调用平台实现的，比如我们这个时候呢希望华立板多做一些工作，在联网的同时呢给用户播放一段声音，呃这个只是一个表示啊，当然你可以做各种各样的扩展操作啊，比如我们在这个发送消息的时候播放一段声音发送图。
片的时候播放一段声音啊等等这样的一种。
呃总之这个功能的实现，perfect的业务抽象的功能实现和这个light版本的业务功能的抽象实现呢是不一样的。
那么我们再回来呃来看一下啊，我们先往下拉，就是说那么mobile版平台也是有一样的需求，对不对？
也是有精简版啊。
那当然因为我们虽然在不同平台上，但我们这些功能的事儿都是一样的，比如说精简版的实现都是一样的，所以呢我们这个偶尔的虚函数的方式也都是一样的。
然后在这里面调用这个只是调用鸡肋，不一样，对吧？
这个调用是mobil，master的鸡肋。
mobile，method，▁，ver，s，ion，text，moba，message，the，装卸。
然后还有一个我们perfect的版本，这个perfect的版本跟咱。
那那个pc上profile版本也是说业务功能的这个这个这个流程是一样的，但是具体里边调用的时限会有些不一样。
比如说mobile，music，based，down，top，lesson，啊调用mobile、business，the，connect等等这样的方式。
呃当这样写下来之后，你再去用的时候，比如说我要创建一个moba平台的message，我就需要通过这样的一种方式。
呃moba，message profile，我们说这是一个编译室装配的方式，但这个也不好，对吧？
不好在哪里呢？
我们还还是啊大家可以想一下这个整个类图啊，我这里就不画这个，大家自己来画一下啊，就是message作为一个积累，对吧？
master，bad，pc。
base和moba。
base啊，两个子类，对吧？
哦那pc message呃pc贝斯底下又有两个子类啊毛表底下也有两个子类，大家想这个似曾相识是吗？
如果我们把pc就平台实现的这个部分的变化列为n的话，啊，然后把那个业务抽象的这个部分列为m的话，想想这个类的数目。
这个数目有有多少啊？
一加n加m乘以n，是吧？
对吧？
你这个这个分支嘛就这里不是阶层了，这个没有必要，就是说这个这个不像detail模式，light和这个profile有组合的情况，他们没有组合的情况，他们就是但这个类的数目其实也挺恐怖的，你想。
m，如果是五的话，n是六的话，这是多少啊？
一加五加五乘六，三十六个类，对吧？
不不不，为了实现这点功能你要做三十六个类，问题是什么？
这三十六个类里面又有重复性，哪里重复性呢？
大家来看啊，比如说pc profile这个函数，八十二行到八十八行和一百三十行到一百三十六行是不是也是有点似曾相识的重复啊？
对吧？
但这个重复也是一种结构性的重复啊，就是你在实现这个profile的时候，你你会发现哦就是一百三十三行、一百三十五行和咱们刚才这个这里边。
对吧？
就和这里边呢八十五行、八十七行都是重复的，就不一样。
在哪里？
在八十四行、八十六行这里不一样，对吧？
一百三十二行、一百三十四行，字类的不一样，但不一样中间又有一样，你很快就发现他们哦他们都是同样的虚函数，是吧？
所以这里边很快的，如果有data模设计模式的这个基础的话啊，大家很快很快就会发现，我原来我应该把这个父类变成什么字段，是吧？
变成超员，喊数据成员。
好，我们这样来变一下啊，我知道是不是声明一个message的抽象指针，大家这这个时候知道为什么。
我要生成纸证明是指针了吧？
指针才在这里才具有多态性，对吧？
好，我把它写下来。
那这里面就是调用这样调用了，对吧？
message，the connect，message，the rock。
text。
method。
的。
johnny。
好，这样写。
然后再来看mobile的light版本，moba，light版本是不是也是一样的？
要把这个东西移下来，继承转组合，是咱们一个非常伟大的一个一个手段，是吧？
message。
好，然后呢再把这个。
拿过来变成指针，是吧这个也变成指针。
好，当我写到这里，很多朋友马上就知道了。
哇这这个现在不一样在哪里？
就是一百一十一行和一百呃和五十九行不一样，那这俩不一样的东西又太少了，对吧？
你很快就会发现哦，原来他们可以声明成同一个积累。
message，然后让他在未来可能是pc message被对吧？
然后在下面这个地方，让他在未来可能是moba。
message，the base。
这这个未来就是运行时，对吧？
好，当我们这样写下来之后，你发现这俩类已经没什么区别了，对吧？
moba，message，light，pc，master，light。
它的区别在于未来运行式的去这意思，你就可以把它名字取掉，p，c取掉。
然后这边模板一去掉之后，你发现哦这俩类一模一样。
ok，可以删掉了，对吧？
重复性可以去掉。
好，当去到这个之后呢，大家拿到这样的一个东西啊，message，light的版本。
当然接着这个呃message，perfect，profiture也是可以如法炮制是吧？
一样的做法在这里啊。
然后把这个鸡肋去掉啊。
好，那么再把这个地方换成指针的调用，推上。
connect，listen，the，connect。
是不是呃跟document模式非常非常像啊？
这也是大家发现我为什么把它两个归到一类了吗？
啊但是它有不同的地方哦。
好。
那当然，写完这个之后，你发现某版master profile已经没有存在的必要性了。
消除重复性可以把它们去掉了，是吧？
好，当做到这个地方的时候。
嗯。
那你就会发现我们很多东西啊都变成了n了，对吧？
但是别急，这里面接着冒出了一个问题，很多朋友可能敏锐的朋友应该发现了，五十九行这个地方是不成立的，你有message base，你会发现message base是一个什么类啊是一个抽象类。
为什么他这个或者咱们在c加加里面叫纯虚积累，为什么呢？
你只over red的部分序函数，是吧？
另外一些传序函数你没有override，那这个问题怎么解决呢？
大家再往上你再去想这个问题的话，你会发现那么message，light为什么有这么几个这么几个版本？
login三的message朝朝气，他也是指o。
re的其中的三个。
函数，另外几个函数没有oled，对吧？
如果你去继承message的话，是不是？
那么你就会发现哦原因是什么？
这里边这这两波东西啊你塞到一个类里面是不合适的，应该把他们拆分开，是吧？
好，我们做一个拆分啊。
在这里做一个拆分，把这个部分去掉作为第一个类，然后把这个地方去掉，作为第二个类，然后呢起个不同的名字，我们刚才其实名字上已经写出来了，有点类似啊就是这个是一个平台实现，我们就加一个i、m、p，好吧？
对吧？
这个平台实现那就放在这里哦。
叫他们去over red。
你的你的play上的就是了，对不对？
然后呢这边也是，好，当当我们这样写的时候，我们这个里面是不是塞的是这样一个指针啊？
对吧？
然后呢再继承public message，是不是这样子？
好，当然这个这个地方啊你就可以呃为了那个什么还是写成这个吧啊mp一。
一，避免混淆啊，把这几个都换过来，这个也换过来。
好，那这边马上就换完了。
那我们就拿到了这样一个东西，然后这个message profit要继承public。
message。
这也是继承转组合，对吧？
就变成组合了。
然后这边就是点点点啊就是以后有各种变化的情况啊，可能性这个地方也是点点点以后各种变化的情况。
好，当做到这里已经接近完美了啊那当然这里面同样的，咱们马丁福乐啊嗯重构里边仍然讲了什么需要如果同样的类里边一呃的子类里边有同样的字段，把它往上提，是吧？
咱们看这个是不是都在同样的这个底下，那就往上提。
提到哪里？
提到mac这里是吧？
大家看，这里合计零，是不是重复啊？
都有，对吧？
都有。
就往父类去扔啊，给他扔到父类，他的父类在哪里？
在这里是不是让protected是不是这里？
这样的话这个就可以没有了。
去掉它是不是这里也去掉它？
当然这个你需要加一个自己手工去加一个构造函数的调用啊，就是父类放一个构造函数去初始化这个字段，对吧？
子类呢放一个构造函数去调用父类的构造函数就可以了，这时间关系我就不在这里写了，当你写到这里的话你就会发现诶那我使用的时候怎么样用呢？
嗯这里的message是吧？
首先呢是不是先。
等一个这个message。
mp。
implementation是吧？
啊这个是。
m，m，p等于new。
然后这是pc的。
当然这个地方我们不要用贝斯啊，就写成mp好了，对吧？
比较比较合适一点啊。
这个毛表就写成mp，是不是？
好，那拿着这个然后new，捏出这个东西，然后这个mp是不是可以？
这样塞进来。
ok，这个叫什么？
这个就叫运行式装配，是吧？
就是运行是把它们组合在一起，这就是一种组合的技术啊，而不是一种继承的技术。
对，走到这儿就比较完美了，对吧？
大家再看这个时候类的个数是多少个啊？
有没有发现是家的关系，对吧？
一加n加m，但是我运行时我还是有n乘以m的功能，就是他们他们互相可以可以交叉组合，对吧？
所以这就是咱们的巧模式。
对，咱们反过来思考刚才的问题的话，你就会发现其实你在一个类里面啊第一个版本里面，你在一个类里面放了不同的函数，就是这些。
也和这些啊它是它是不同的变化方向。
一个方向是我们所谓的平台实现，一个变化方向是我们所谓的业务抽象啊平台所谓平台事件就是pc、mobil啊、tv什么、pad之类的，对吧？
所谓的业务变化方向就是light版本、perfect版本，可能还有什么binds版本，各种各样。
这两个不同的变化方向带动的行为的多态的实现也是应该往不同方向走，你就不应该把它放在一个类里，对吧？
这个时候我们再咱们再回到啊回到咱们的这个这个slice里边来看一下，就会比较明白这个问题了，对吧？
有没有看到我们刚才讲的多个变化的维度或者。
就讲两个变化的维度是什么意思啊？
那g、o、f给我们的这个这个妙招是什么？
将抽象部分，我这里有个括弧，这是我们的业务功能与实现部分，就是咱们的平台实现分离，使得他们可以独立的变化啊这个独立的变化的方式。
我们来看一下类图一样的这个地方，首先呢这个是一个稳定的鸡肋，对吧？
这两个都是稳定的鸡肋，大家看a鸡类和b鸡类，对吧？
action就是咱们的那个嗯message，是吧？
然后那个intel，mental呢就是咱们的message，in，parameter。
然后里边呢记住。
这个里边有一个指针，是吧？
appstore有一个多态指针指向internet，就是咱们的message里边有一个多态指针指向那个message。
i，m，p，对吧？
啊然后各自有各自的子类，你有你的子类。
action，你有你的子类，对吧？
我用蓝色的笔来画啊就是它的子类就是变化，对吧？
好，那这是你的变化，然后我有我的变化，平台实现有平台实现的变化，对吧？
就是这个computer，implement，a就相当于咱们的pc。
message，implemented，对吧？
然后呢computer，important，b就相当于咱们的mobile啊呃这个这个message，mp，然而reforms，extraction相当于咱们的什么later版本，perfect版本啊，就两。
各变化的方向独立来变化，而不是像之前一样搅在一起变化，对吧？
就放在一个鸡肋里边啊，两个两个变化的方向会打架，对吧？
你你有一种强烈的感觉就他们在打架，但是当你通过这样的设计模式把他们宅开之后，你会发现他们很相安无事是吧？
而且会很好地组合出针对未来的这个需求的变化啊。
设计模式的精妙之处就在这里啊，这个bridge的模式。
好，那我们做一个总结啊。
首先呢我们说prada模式使用是对象间的组合关系，这个组合的最关键的这个关系啊就是咱们前面那个那个里边塞了一个抽象的指针，是吧？
择偶了抽象与实现之间固有的绑定关系。
是的。
而抽象和实现。
可以哎可以沿着，我还是有点强迫症的啊，我比较在这个地方喜欢用红色，所以我把那个蓝色的删掉，重新化成红色，使得抽象和实现可以沿着各自的维度来变化。
所谓抽象和实现沿着各自的维度的变化呢就是子类化他们。
嗯不是，这模式有时候类似于啊咱们这个c加加里面有些多继承的方案啊，但多继承方案其实往往违背单一职责原则，我们不推断它呃不推荐大家使用啊，复用性也比较差。
我们一般呢在c加加里面还是推荐就说一个单继承，其他地方用组合的方式。
然后标识模式应用一般在两个非常强的变化维度啊，有时候一个类啊也有多余两个的变化维度。
就你可能也有三三个变化维度，也可能有四个变化为，对吧？
当你有这样这个多个变化维度，breaking模式其实都给大家提供了一个方向，什么方向呢？
就是把其他属于其他变化维度的东西给他合在一起，就某一个聚合的变化维度啊合在一起打包成一个鸡肋，然后用一个抽象指针指向它，对吧？
如果你有三个变化维度呢，就把三个部分摘出来，用三个抽象指针指向它，就是breaking模式的精妙精妙的地方啊。
好，那我们今天这个breaking模式就讲到这里。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br><span class="line-number">177</span><br><span class="line-number">178</span><br><span class="line-number">179</span><br><span class="line-number">180</span><br><span class="line-number">181</span><br><span class="line-number">182</span><br><span class="line-number">183</span><br><span class="line-number">184</span><br><span class="line-number">185</span><br><span class="line-number">186</span><br><span class="line-number">187</span><br><span class="line-number">188</span><br><span class="line-number">189</span><br><span class="line-number">190</span><br><span class="line-number">191</span><br><span class="line-number">192</span><br><span class="line-number">193</span><br><span class="line-number">194</span><br><span class="line-number">195</span><br><span class="line-number">196</span><br><span class="line-number">197</span><br><span class="line-number">198</span><br><span class="line-number">199</span><br><span class="line-number">200</span><br><span class="line-number">201</span><br><span class="line-number">202</span><br><span class="line-number">203</span><br><span class="line-number">204</span><br><span class="line-number">205</span><br><span class="line-number">206</span><br><span class="line-number">207</span><br><span class="line-number">208</span><br><span class="line-number">209</span><br><span class="line-number">210</span><br><span class="line-number">211</span><br><span class="line-number">212</span><br><span class="line-number">213</span><br><span class="line-number">214</span><br><span class="line-number">215</span><br><span class="line-number">216</span><br><span class="line-number">217</span><br><span class="line-number">218</span><br></div></div><h2 id="_08-工厂方法"><a href="#_08-工厂方法" class="header-anchor">#</a> 08.工厂方法</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>好，大家好，我们开始我们今天呃c 一家设计模式的这个factory method。
啊，工厂方法模式。
呃，首先呢呃我们说这是一个新的类别啊，那我们把它归结到对象创建模式里面。
到时候来看对象创建模式，我们强调的是什么？他实际上是绕开我们传统的这样一个创建方法，就是以你为代表的这种创建方法。
来避免对象创建过程中所导致的一个蹇有合。
啊，从而支持对象创建的一个稳定化。
嗯，那我们后面有一句话叫做它是接口抽象之后的第一步工作。啊，那我们对象创建模式呢有这么四。
这四个模式啊，那么其实这四个模式呃非常接近啊，他们解决的是同一个问题啊，只是说这个问题在。
不同的这个演化过程中呢，有一些细微的一些细节的不同，所以需要使用四个不同的模式来来来去应对啊。
那我们首先来看一下呃。
工厂方法模式是怎么解决这个问题的？
当然这个问题呢首先要描述清楚啊，就是在软件系统中呢，我们的经常面临着创建对象的这样一个工作。由于需求的变化呢，你创建对象的具体类型经常变化。
啊，好还是。
回到代码上来看一看啊。
呃。
那我们来看一下这个代码呢。
我把我们之前的这个呃呃之前。
呃，大家听那个就是呃其他的一些模式，比如说观察者模式的时候，我们曾经讲过一个例子，对吧？一个文件分割器的例子啊。
那我们把这个例子稍微抽象一下啊，把跟有观察者模式和其他模式不相关的东西啊，跟我们现在讲的不相关的业务，把那些代码给他。
摘掉。
咱们只突出啊跟我们现在创建型模式暴露出的问题，相关的代码结构啊。
呃。
好，那么咱们来看一下这个嗯。
很简单啊，一个文件分割器file splitter，它里边的一个核心行为是这个split 方法，对吧？然后呢我们这里呢通过收集参数啊等等，然后创建一个splatter 这样一个对象，然后调用。
慈悲的方法，然后来完成分割。呃，这是一个再正常不过，再简单不过的一个对象使用模式啊，那我们说。
他有什么问题呢？啊，当然他一般来讲是你单独看啊，看不出问题来了啊。但是我们说咱们在一个变化的场景来去看问题。
你就能发现一些蛛丝马迹啊，那首先呢我们说一般意义上咱们之前曾经讲过一个呃类型啊。
你要看到他未来的变化的需求。这个时候呢你就要去做抽象类啊或者是呃接口，这就是我们。
最早的讲的一个设计原则叫面向接口的编程。
面向接口的编程告诉我们啊，你一个对象的类型往往应该声明成抽象类或者接口就是十四行。这里。
而不应该声明成具体的类。
对吧，如果你声明成具体的类啊，其实呢就念就意味着你这个是没有什么没有支持未来的变化就定死了，对吧？他永远就是这个。
那当然这个反过来就是说我们要去判断这个有没有需求的变化。
是吧那么我现在就假想，其实啊比如说在我们这个需求里面。
可能有一些变化，举例来说。
我们现在是一个文件分割起的，呃，比如说我们支持只是以二进制形式的文件分割，但是呢我们可能也会未来去支持什么。
呃，举例来说啊，文本文件的分割啊或者是图片文件的分割啊呃或者是视频文件的分格。
等等对吧？比如说我们要有txt 啊split。
slater 啊，这样的啊文件分割。
然后呢，我们也可能有，比如说啊picture。
啊，split. 
啊，this later, 然后呢，这是图片文件的风格，我们也可能会有一些比如说video 文件的风格。
因为不同文件啊格式的话，我们就我们在分割上分割算法上，我们可能希望呢支持一些。
不一样的一些东西啊。videos later. 
好，那当我们把这个呃这个呢我们就给给他直接写成什么改成finery。
slater 这样的一个方式。
好，当然这个具体大家了解这个我就把它先给它抽出去啊。就是假设咱们有这么一些分割器，那么当然你这个。
就是当你想到这些变化的时候呢，你就需要抽象出你的鸡肋啊嗯。
抽象基类是什么呢？我们就是说比如说一个i split。
啊，那他底下呢有一个这样的一个，比如说virtual。
void split 方法。
对吧，当然可能还有别的去方法啊，就我们这个例子啊演示作用，我们啊我们只放一个虚方法就可以了啊。
当然处于啊我们说抽象基类的一个。
嗯，内存管理啊资源释放层面的安全性的原因。我们需要写一个学期构函数是吧？
呃。
啊，这里面需要加v tur 吧。
啊，这是我们常常所做的一个工作。那么当然这个底下都要去。
去做这个继承是吧？
是不是要这样去写啊？
去继承了，然后。
具体实现代码我就不写了，大家要在这里面去实现你你各自的这个split 方法，对吧？
好，这是咱们常常所做的一个一个面向接口编程工作的一部分。
大家回想一下我们之前的设计模式啊。
对吧，桥模式啊。that create more bridge. 呃，这这个这个呃呃呃不是我观察者模式等等啊strategy 这所有的模式。
背后都有一个什么抽象基类，对吧？这是这是你是就是我们说面向对象设计模式所说。
基本上的一个一个基础啊。
好，那有了这个呢。
他们面临的接着大家要做一个工作，就是说你要这样去写。
对吧你要把你这个sales later 呢换成这个。
这个就是我们讲面向接口编程。
面向接口变成最险最简单的一个表现形式，就是你的变量要声明成抽象基类。
对啊。
那么后边呢怎么办呢？
接着的问题，后面这个地方。
首先咱们要说为什么要实现面向接口编程啊。
大家再想一下，我们是不是有一个原子设计原则叫什么？
呃，那这个。
依赖倒置原则的，因而导致原则是什么？应该去依赖呃抽象，不应该依赖实现细节，是吗？
好，那然后看十四行已经变成依赖抽象了，是吧？我们讲的依赖就是编译时依赖啊，就是我编译的时候，你这个这个需要需要你存在，我才能编译通过，对吧？这个就叫。
一是依赖。
然后呢十五行呢，大家看。
这个是一个细节啊，当然在我们现在其实是应该换成一个binary ies later，是吧？
好。
呃，十五行是一个细节以来。
呃，十四行是个抽象以来。
那这个也不行，对吧？你你代码中间你只要出现一触式细节依赖你这个哪怕你其他地方都是抽象以来也解决不了问题。
啊，也把这个这个原则给打破了。
简单来说就是这个没inform 呢，你在编译的时候，你总体还是要依赖b y splitter 存在，你才能编译通过的。
所以你实现了一个什么呃边意识的这样一个细节依赖，这个就也是违背我们依赖倒置原则的，是吧？
但是这个东西。
怎么解决呢？对吧？大家想呀，你你简单的把这个换成splatter。
这这这个肯定不行的，对吧？那大家知道在在任何一个编程语言抽象基类或者接口是不能去创建的，对吧？是不能去new 有的。
啊。
那你应该怎么办啊？
这个就是咱们刚才讲的啊，我们回到我们ppt 就是首先要清楚问题很多学习设计模式的朋友呢，刚开始都不知道设计不是要解决什么问题。呱唧呱唧就去。
这去学这个设计模式的这个。
马结构了，学了半天都搞不明白。既然你去一个城市，你都不知道你的目标是什么，你怎么描绘你的路线图啊，是吧？所以你的目标一定要清楚。
那么我们就是说大家的问题一定要就解决解决什么样问题的，对吧？再回过来啊，大家来看一下我们p p t 里边讲的这句话，是不是就。
比较清楚了啊。
就是通过对象创建模式绕开new。
大家知道为什么要绕开new 啊，我们刚才说new 有这个依赖带来的不好，对吧？你带来的是一个细节依赖来避免对象创建，就是new 殴过程中导致的。仅有盒。
就是依赖具体类。
啊，那我。
把这个如果加一句注释，就是这个就是啊。
这个就是咱们的伊赖依赖具体类啊，食物行，就是依赖的具体类。
他就不好啊。
对吧那么对象创建模式就是要我们现在的目标是什么？要绕开这个new 带来的问题。
我们刚才也说了，他是接口抽象之后的第一步工作。或者这句话也可以理解成它是面向接口编程必然的提出的一个需求。
就面向接口编程，你不能只管等号左边对吧？你不能只管十四行，而不管十五行等号，右边这个事儿啊，你两边都要把它变成接口。
这样把它变成依赖抽象，而不是依赖具体。
好，那怎么解决呢？
嗯。
我我我我试图带大家从最原始的这样一个编程的思考层面啊，就是咱们不要一下来就是设计魔术。我一直不主张大家一下来。
一上来就拿出一个结论给大家说这是什么什么什么啊，所以我们一定要抽丝剥茧去还原他最初的这个设计场景。
好，这个最初的设计场景是什么？就是说现在问题已经出来了，对吧？那怎么解决？大家想一想。
在cgi 里边，你创建一个对象有哪些方法？
另外一种方法可能是这样子是吧？
d s 十四行这样子是吧，然后挂哇，它放一堆东西。
这也不行啊，对吧？这也是个具体类，那那是家里面能不能像十四行在这样子做，肯定不行，对吧？这个就是说一个一个抽象基类，我们说不能。
直接创建一个对象了。
这些就是你你用这家单独的，不管是在赞赏声明对象，还是在堆上去，new 这种方法都不行。
对吧？
那怎么办？大家想想创建对象还有什么方法？
嗯，还有绕的方法对吧？怎么绕呢？比如说我不能用，你有不能用直接呃这个这个战事在栈上创建对象的这种方式。
我是不是可以用一种方法来返回一个对象？
可以吧，这个在咱们这个也是很很正常的，对吧？你可以用一个方法，其实你也可以理解new 就是一种方法，但new 只不过是一个特别特殊的方法。
而已啊，那我们自己可不可以做另外一种方法，让他来达到我们的目的。
好，大家来来推敲啊，一起来推敲这个过程。
好，我们假设我们现在有这么一个方法。
呃。
我来写这个方法啊。
比如说我们这里啊有一个嗯我这样吧，为了考考虑那个设计的原因啊，我把这个方法呢。
到啊我们另外一个文件里。
否则这个这个越写越大越写越大啊，这个大家就。
最后会被弄晕了。
好，我在这里。
那我我不要这些了，我就直接写出一个class。
啊，later. 
factory. 
所以这个工厂方法的模式是大家一定要啊呃深入去理解的。只有你理解他，其他的其他模式就非常快啊。
大家其他模式很快就可以理解了。好，我把这件拿掉。
这些拿掉啊，我先写一个，比如说我现在定义一个方法。
好，我定义一个什么样的方法呢？假设定义这样一个方法。
void 呀，然后呢呃呃他需要一个一个具体的返回值，对吧？
i splitter. 
啊，比如说create。
splatter. 
好。
那在这个里边呢，我return 一个什么呢？对吧？当然这这个我们知道不能返回对象，只能返回指针是吧？这个地方是不是要retain 一个new，就是堆上的对象是吧？
又出来一个嗯。
那能不能这样写，i o s later. 
仍然不能这样写，对吧？你如果放一些参数啊，但你这个也仍然是可以可以放一定的参数的。假设我们现在播放参数。
假设咱们咱们其实你也可以把这个前面这些这些东西都忽略掉，就都忽略的啊。
对，这些都忽略了，就就用最简单的形式，最参数，你以后可以考虑加上去。
好，那。
我们能不能这么干，也不能，对吧？
那么你需要怎么干呢？
呃。
比如说这里面还需要放具体的类，对吧？因为你你要去new 的话，你必须写具体类啊。
好，那假设我们这样去写，能不能解决这个问题啊？
其实还是没有根本上解决这个问题，对吧？我现在这样写了之后呢，我写一个缝没form 二啊，大家来对比。
啊，设计模式一定要在对比中才有才有收获啊，才会理解的。为什么？
好，那我们来看一下。
这边呢？
我我怎么做呢？
我这边有一这样一个i s later factory 是吧？啊，我假设我现在现在这样去放。
actor. 
啊，那咱这就是调用它里边的一个方法，对不对？
好，他去create at 什么？
可以在咱们这个斯platter 上。
呃，虽然这么做啊。
好像是有一些改善是吗？大家看一下啊。
呃。
这个的返回值是一个slater 的，但是呢就有问题还没有解决。为什么呢？大家看一看这个依赖关系啊。
splatter factory 要不要依赖一个b y splitter？
是要依赖的是吧？
那编译时依赖啊，我这里强调的，然后这个这边没form 呢。
他要不要依赖这个呃a s later factory 啊，太要依赖对吧？那就是说没放，我们依赖是speaker factory factory that a factory you 依赖binary。那当然最后。
没放过，仍然要依赖b y s later。
对吧，就是你的间接的这样一个依赖关系，你你都是编译时依赖，那你最后仍然导致啊你去依赖他了。也就是说你你。
你其实绕了一层，还还没有把这个问题绕绕出去。
呃，当然这里创建的是实例方法，对吧？你也可以创建静态方法啊等等，你你还是绕不过这个问题，那怎么办呢？
当前啊还有还有啊什么设施啊？
其实我们自己家里面还有一个非常独特的设施就是。
我现在这个是编译时依赖大家想想我们有什么样是一个运行时依赖。
你有要这个这个virtual method，对吧？虚函数啊虚函数是一个。
哎，运行是依赖，所以他给了我们一定的启发。怎么样启发大家来看啊，我在这里呢可以做出一个虚函数。
假设我这里面写了一个炫函数。
对，既然我写的渲染树，我就不必。
现在就写这个对不对？虚函数就是一种延迟啊一种延迟的。
延迟到运行时。
好，那我把这个写成这个样子。
啊，当然这个地方也是要去。
哎，要去考虑家这样的一个。
程序积累对吧？这是呃这这个。
呃，virtual 的吸构函数啊。
啊，所以任何一个程序积累都需要一个窝趣吸构函数。好，当我这样一变化的时候呢，大家就会发现有意思的地方出现了。
哎，我这个地方。
啊。
我这个地方是不是这个依赖关系其实是理顺了啊，但是我们都知道他要交给未来。
对吧，因为它是调用一个虚函数，当然也因为这是一个纯。
第七类，所以这边你应该用什么用指针的方式。
对吧，用指针的方式。
然后呢。
这边去调用。
好，这个是不是就是有一个多态性了，大家看啊十五行这个地方是一个多态，多态的创建。就是我现在。
呃，创返回值是sv 塔，但是我真正创建那个对象交给未来，交给哪个？未来呢，交给s plate factory 这个未来。
好，当然这就接着一一一遇到一个问题，我未来这个split are factory 放什么呢？
是吧我可以放任何的具体的factory。那具体三水在哪里？好在这里我们来写。
我们来找找我们的这个代码啊。
呃，刚才呢我们在我们是这样的一个面向结果的编程方式，对吧？嗯？
好，我们也创建出第二个版本啊，二点零版本。
好，这个二点零版本里边呢，我们就需要针对咱们刚才的那个工厂。
我就我当然这个可以可以删掉了，是吧？因为其实这个这个东西都已经在这里了啊。
好，那这是我其实这个先后次序啊，应该最好这样放一下吧。
啊，这个s date 这个是咱们家的一个工厂，对吧？那这是什么？针对，这是具体类。
具体类啊。
呃，那我们针对这些具体类要创建一系列的具体工厂。
是吧一个一个具体的工厂。好，这个具体的工厂怎么做呢？当然很简单，比如说我这边。
是这个。
bannister, 我就可以写一个banner。three or factory. 
集成一个public。
sweater factory. 
是吗？
好，然后我就可以去重写这个虚函数，是不是？
好，当我去重写这个渲染树的时候。
我里边返回谁呀？
我当然就是return 一个，你有一个finally。
但再加一个class。
这个。
然后呢，是不是你有一个这个。
对不对？这是具体具体的工厂。
啊，然后当然每一个类其实都应该有一个对应的具体工厂，是吧，就是。
你可以有banner ary s later。
啊，呃splitter back tory。当然我也可以有什么txt。
split by query. 我这边给他换成txt。
slater 是吧啊，可以继续做下去啊，我把这几个都都都填上去。
还有一个是什么picture 是吧？
好，这个pictures with the factory picture are later。是吧？
好，这边呢？
一样的video。
plate factory 这边就是video。
later 是吧。
好，那有了这样的一些东西之后呢。
啊，大家就会。
发现啊我们这里每一个啊这个具体啊这个factory 少写一个。我爱。
啊。
加过来。
好，当然这样写完之后你就会发现哦，我的每一个工厂。
转每一个具体的类都应都有对应的他的一个具体的工厂是吧？所以我将来我在没放牧二里边做事情的时候呢。
我这个未来这个就有着落了，是吧，这个问号啊我就可以试那些具体的工厂。
但是。
你在这里能不能直接把那个具体工厂写过来啊？
首先我说啊，这不可以不可以写在这里，应该写在哪里呢？
其实大家要明白，就是我们实际上呢通常是把这个。
放在这里。
他是只需要一个工厂就可以了。因为为什么呢？因为我们的八乘以一click 啊，它是被可以被反复点击的，对吧？
他是他需要多次点击啊。
嗯，那么你不需要创建多个工厂，对吧？不需要，就是这个东东西也有多个，你这个只需要一个就可以了，那么。
具体他是什么啊？那么在may form 里面，你不需要去指定它。以一般意义上啊，我们很多时候实际上是这样来做的。
nform 里边啊。
咱们通常我把这些其实无关的都给他拿掉了。
我们只放这个may form，比如说它的构造器。
通常呢我们是把通过外界传递进来一个factory。
就是这里这样的话，比如说factory。
等于factor。
好。
这样就解决这个问题了，是吧？我从外界，我未来将来从外界传递某一个具体的splatter。
我可以传递，比如说binary slater 的话，那我这个地方今后创建了就是一个。
findlater. 而且就传的这个banner better factory 的话，我这边创建出就是一个banner。
如果将来创建是一个video 的，塞进来的是一个video 的sweater factory 的话，我这边就可以反复的去创建啊一个。
video 的。
是吧那这个这个地方我们形式上把它叫做什么多肽new。
多太牛。
太堵的太啊。
多态的一个妞。
对吧，就是释迦r 语言机制本身没有提供，你有没有给你一个多态的有，但是我们通过虚函数创造性的解。
啊，做出了一个多态按钮。
而这个就是一个工厂。
当然我想肯定有朋友会提这个问题，要是这个factory were 以后呢。
我我虽然不在没放牧里边去去解决他，对吧？就是创建它，但我factory 未来在其他的地方是不是也要创建它？
video splitter factory 啊或者是pictures is let the factory。and 呢，对吧？
那是不是也产生依赖了，对这个问题提得很好，会产生依赖。但是呢在我们先考察没父母这个依赖有没有？
有没有产生依赖，有没有对就具体类产生依赖。
大家看通过这样的改良之后，你会发现雷form 再也没有具体类的依赖了，对吧？
我这里面第三行依赖的是什么？
three later factory 是一个抽象基类。
isv 特是不是一个抽象基类，都是抽象积累。
对吧？
我没有依赖具体类，至于你没放过以外的不归我管。
我总之我里边不依赖具体类了。
呃，这个can back k 啊，一个面向对象大师曾经讲过一句话啊，就咱们设计模式或面向这样的这种松耦合设计。很多时候实际上呢。
并不是把变化给消灭掉了。
也就是说，并不是把依赖具体类的这个事情给消灭掉了，你消灭不掉的。而实际上是把它赶到某一个局部的地方。
啊，它比比呃举了一个例子，就是说就好像啊你把一只猫大家把把变化当做一只猫啊给他关到笼子里。
而不是把他让他在你整个这个代码里边乱跳来跳去。
对吧，就没奉母仪的方式，就是让这个变化。大家看这个变化就是在你的屋子里面跳来跳去。
当然我这里面只举例子期间啊，我只写了一个地方，以实质这样想想一想，你真正在你创建对象的地方，不光你把他ekk，也需要创建这个对象，你还有可能更多的地方需要创建这个事情，对吧？
你所有地方都产生这样一个具体依赖，那这个就是变化在充斥了你的泪啊的设计。但是我们通过这个方式把变化什么不是把电话消灭了。
而是把变化赶出去了，赶到某一个某一个局部的地方。啊，这就是我们这个工厂设计模式处理事情的艺术。
啊。
好，那到这里其实就得到了一个完整的工厂方法的模式。
啊，这个工厂方法的模式里边呢，大家再来对照看一下代码啊。
啊，我们我们还有一个一个代码，就是splitter 一的这个啊。is this the back? 
二二啊。
对，一个是这个这个部分。
啊。
一个啊一个是我们没form e 先把它拿掉。
还有一个是我们的split actor 的是吧？大家对照这两个啊。
这是我们的这是我们的抽象类。
抽象类是吧，这是我们的具体类。
啊，这是我们的工厂。
呃，我不适合在这里说，他说他是一个抽象工厂，因为我们抽象工厂是一个特殊的模式，我们的或稍后再讲，我们这是一个工厂。
呃，工厂鸡肋吧，我就下。
嗯。
这是一个工厂鸡肋，呃，这边是一系列的具体工厂啊，这就咱们这个设计啊呃然后呢。
形成了依赖关系，看main form 是依赖。
据抽象的。
这两个东西，而不依赖这些东西啊，一这些东西被什么被隔离出去了啊，格力的一个其他的地方就是你要需要初始化那个没form 的地方。
啊。
好，回到我们的p p t 啊来。
这个时候对照咱们的这个讲的这些理论性的一些抽象的语言，就就更理解了，对吧？
好，我们来看一下这个工厂方法模式定义定义一个用于创建对象的接口，让子类决定实例化哪个类。
子类是谁啊？
那这个代码上来看，定义一个用于创建对象的接口在哪里？
在这里。
这是创建对象的一个接口啊，具体就是十三行这个方法就是负责创建的。所以这个方法其实就是我们的这样。
是工厂方法，然后咱们工厂方法这个设计模式就来源于这里啊，名字就来这里啊。
创建对象就让子类决定实例化哪个类，这就是子类是吧？这个类决定实例化这个类这个类决定实例化这个类啊。
pictures with the faculty 决定实例化a pictures later。啊。
section myself 的这个模式呢使得一个类的实例化延迟啊得到了延迟啊。
延迟就是支持了变化，延迟到什么延迟到了。
啊，目的是什么？是结偶对这这个这个括号里面是我家的注释啊。
就目的是为了解偶解谁谁和谁之间的耦合呢？就是new 后边跟的那个具体类的偶像手段是用什么？用虚函数。
啊，所以咱们一呃我在讲，一是咱们面前那样课程一直三番五次强调虚函数的重要性，对吧？大家也也从这里能够看到啊。
好，然后我们再来看这个图。
啊，这个图是不是现在就很清晰了，能不能对应起来哈？
prod k 是谁啊？
就是咱们刚才这里的。
啊，i splatter. 
是吧pro product 就咱们splatter。
康create product 是谁？
是这些。
finally, later, text the a platter, pictures later, videos later. 
啊，然后这个creator 是谁啊？
这咱们的sweater factory 这样一个工厂鸡肋啊，然后这个concrete slater 是谁呀？就是咱们这些啊finders。this factory are text. 
i actually are features the factory videos, let the factory. 等等。
对吧，通过这个其实就看出来了啊，然后没form 和谁依赖呢？may form 纸盒上面这个部分依赖。
对吧？好，那我们把这个在在最大化一下，我把这个咱们这个b 掉出来了。
嗯，他们还是依照我们之前的惯例啊，画一下红色的部分是稳定的。
是吧没inform 就依赖的是红色的部分啊。
蓝色的部分我换换换一个笔啊。
蓝色的部分是变化的。
na inform 就不依赖他们。
对吧我们的做法就是让让我们什么把蓝色的隔离出去啊，让我们main form 去依赖红色的。
因为红色部分是稳定的。
啊。
形成这样一个认识啊，就是看到任何一个一个设计模式的类图的时候，你一定要眼光立即看出来谁是稳定的随时变化。
要。
好，最后做一个总结fact，master 模式用于隔离类对象的使用者和具体类型之间的耦合关系。
面对一个经常变化的具体类型啊，紧耦合关系会导致软件的脆弱啊，然后factory method 模式通过面向对象的手法。
啊，对啊，是面向对象的手法。其实啊以后还有别的手法，对吧？现在先说面向对象，手法是什么？就是多肽对吧？
将所创建的具体对象延迟到子类，大家一定要注意这些关键词延迟啊，从而实现一种或者。
注意啊，这是扩展而非更改的策略啊，所谓扩展就是我我添加这个factory 就可以了。
啊，我不需要直接对着源代码去，你换一个类，我就要换一种写法是吧？啊，较好的解决了这种紧耦合关系啊。
我再稍微强调一下这个延迟而非更改是什么意思啊？
比如最早咱们南明放牧衣来说。
最早你你需求一变化，你就要改这个代码是吧？十三哈要不断的改这个代码，那这个就不好嘛，是吧？
那我们现在需求变化的是什么？
现现在需求变化了之后呢。
咱们这个地方不动的稳稳坐泰山，对吧？十四行到十五。邢婧雯是个很稳定的，不需要变化，你只需要在未来去加。
加你这个子类和家，你之类的工厂就可以了，加好之后给它传给门缝。they form. 
本身是稳定的。
是吧这就是一种扩展的策略啊。
啊，就是大家要理解这个啊，就是我们讲的这个延迟啊。
嗯，他就实现了一种扩展，而非更改的策略，较好的解决重要耦合关系。啊，那fact my soul 的模式呢解决的是单个对象的需求变化。
啊，他有没有缺点啊他有缺点啊，还要求对象的创建方法参数不同啊，以参数相同对吧？就是你你你这个所有的对象的创建的时候，你如果需要我们刚才举的例子，是不需要传参的。
你如果需要传参，你的参数应该是一致的。你如果参数都不一致，那这个这个fast method 模式是不合适的啊。
呃。
当然现在看这这这个这个总结啊，这个比较理论化的描述是不是就有感觉了啊，这个感觉是什么？你要映射到代码。
你你你读这三段话，每一段的话你都都应该映射到代码啊，你你不能脱离代码去想这些抽象理论化的东西。
当然有一个地方我稍微提一下，就咱们刚才实现这个模式的时候，没有考虑内存管理的问题啊，大家这个其实下去可以补充啊啊我们比如我们很多对象new 了，没有去delete。
是吧有的地方是在factor 里边去提供一个release 的函数，有的是直接去用delete 都可以。
好，我们今天这个fix ms 的设计模式就讲到这里，谢谢大家。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br><span class="line-number">177</span><br><span class="line-number">178</span><br><span class="line-number">179</span><br><span class="line-number">180</span><br><span class="line-number">181</span><br><span class="line-number">182</span><br><span class="line-number">183</span><br><span class="line-number">184</span><br><span class="line-number">185</span><br><span class="line-number">186</span><br><span class="line-number">187</span><br><span class="line-number">188</span><br><span class="line-number">189</span><br><span class="line-number">190</span><br><span class="line-number">191</span><br><span class="line-number">192</span><br><span class="line-number">193</span><br><span class="line-number">194</span><br><span class="line-number">195</span><br><span class="line-number">196</span><br><span class="line-number">197</span><br><span class="line-number">198</span><br><span class="line-number">199</span><br><span class="line-number">200</span><br><span class="line-number">201</span><br><span class="line-number">202</span><br><span class="line-number">203</span><br><span class="line-number">204</span><br><span class="line-number">205</span><br><span class="line-number">206</span><br><span class="line-number">207</span><br><span class="line-number">208</span><br><span class="line-number">209</span><br><span class="line-number">210</span><br><span class="line-number">211</span><br><span class="line-number">212</span><br><span class="line-number">213</span><br><span class="line-number">214</span><br><span class="line-number">215</span><br><span class="line-number">216</span><br><span class="line-number">217</span><br><span class="line-number">218</span><br><span class="line-number">219</span><br><span class="line-number">220</span><br><span class="line-number">221</span><br><span class="line-number">222</span><br><span class="line-number">223</span><br><span class="line-number">224</span><br><span class="line-number">225</span><br><span class="line-number">226</span><br><span class="line-number">227</span><br><span class="line-number">228</span><br><span class="line-number">229</span><br><span class="line-number">230</span><br><span class="line-number">231</span><br><span class="line-number">232</span><br><span class="line-number">233</span><br><span class="line-number">234</span><br><span class="line-number">235</span><br><span class="line-number">236</span><br><span class="line-number">237</span><br><span class="line-number">238</span><br><span class="line-number">239</span><br><span class="line-number">240</span><br><span class="line-number">241</span><br><span class="line-number">242</span><br><span class="line-number">243</span><br><span class="line-number">244</span><br><span class="line-number">245</span><br><span class="line-number">246</span><br><span class="line-number">247</span><br><span class="line-number">248</span><br><span class="line-number">249</span><br><span class="line-number">250</span><br><span class="line-number">251</span><br><span class="line-number">252</span><br><span class="line-number">253</span><br><span class="line-number">254</span><br><span class="line-number">255</span><br><span class="line-number">256</span><br><span class="line-number">257</span><br><span class="line-number">258</span><br><span class="line-number">259</span><br><span class="line-number">260</span><br><span class="line-number">261</span><br><span class="line-number">262</span><br><span class="line-number">263</span><br><span class="line-number">264</span><br><span class="line-number">265</span><br><span class="line-number">266</span><br><span class="line-number">267</span><br><span class="line-number">268</span><br><span class="line-number">269</span><br><span class="line-number">270</span><br><span class="line-number">271</span><br><span class="line-number">272</span><br><span class="line-number">273</span><br><span class="line-number">274</span><br><span class="line-number">275</span><br><span class="line-number">276</span><br><span class="line-number">277</span><br><span class="line-number">278</span><br><span class="line-number">279</span><br><span class="line-number">280</span><br><span class="line-number">281</span><br><span class="line-number">282</span><br><span class="line-number">283</span><br><span class="line-number">284</span><br><span class="line-number">285</span><br><span class="line-number">286</span><br><span class="line-number">287</span><br><span class="line-number">288</span><br><span class="line-number">289</span><br><span class="line-number">290</span><br><span class="line-number">291</span><br><span class="line-number">292</span><br><span class="line-number">293</span><br><span class="line-number">294</span><br><span class="line-number">295</span><br><span class="line-number">296</span><br><span class="line-number">297</span><br><span class="line-number">298</span><br><span class="line-number">299</span><br><span class="line-number">300</span><br><span class="line-number">301</span><br><span class="line-number">302</span><br><span class="line-number">303</span><br><span class="line-number">304</span><br><span class="line-number">305</span><br><span class="line-number">306</span><br><span class="line-number">307</span><br><span class="line-number">308</span><br><span class="line-number">309</span><br><span class="line-number">310</span><br><span class="line-number">311</span><br><span class="line-number">312</span><br><span class="line-number">313</span><br><span class="line-number">314</span><br><span class="line-number">315</span><br><span class="line-number">316</span><br><span class="line-number">317</span><br><span class="line-number">318</span><br><span class="line-number">319</span><br><span class="line-number">320</span><br><span class="line-number">321</span><br><span class="line-number">322</span><br><span class="line-number">323</span><br><span class="line-number">324</span><br><span class="line-number">325</span><br><span class="line-number">326</span><br><span class="line-number">327</span><br><span class="line-number">328</span><br><span class="line-number">329</span><br><span class="line-number">330</span><br><span class="line-number">331</span><br><span class="line-number">332</span><br><span class="line-number">333</span><br><span class="line-number">334</span><br><span class="line-number">335</span><br><span class="line-number">336</span><br><span class="line-number">337</span><br><span class="line-number">338</span><br><span class="line-number">339</span><br><span class="line-number">340</span><br><span class="line-number">341</span><br><span class="line-number">342</span><br><span class="line-number">343</span><br><span class="line-number">344</span><br><span class="line-number">345</span><br><span class="line-number">346</span><br><span class="line-number">347</span><br><span class="line-number">348</span><br><span class="line-number">349</span><br><span class="line-number">350</span><br><span class="line-number">351</span><br><span class="line-number">352</span><br><span class="line-number">353</span><br><span class="line-number">354</span><br><span class="line-number">355</span><br><span class="line-number">356</span><br><span class="line-number">357</span><br><span class="line-number">358</span><br><span class="line-number">359</span><br><span class="line-number">360</span><br><span class="line-number">361</span><br><span class="line-number">362</span><br><span class="line-number">363</span><br><span class="line-number">364</span><br><span class="line-number">365</span><br><span class="line-number">366</span><br><span class="line-number">367</span><br><span class="line-number">368</span><br><span class="line-number">369</span><br><span class="line-number">370</span><br><span class="line-number">371</span><br><span class="line-number">372</span><br><span class="line-number">373</span><br><span class="line-number">374</span><br><span class="line-number">375</span><br><span class="line-number">376</span><br><span class="line-number">377</span><br><span class="line-number">378</span><br><span class="line-number">379</span><br><span class="line-number">380</span><br><span class="line-number">381</span><br><span class="line-number">382</span><br><span class="line-number">383</span><br><span class="line-number">384</span><br><span class="line-number">385</span><br></div></div><h2 id="_09-抽象工厂"><a href="#_09-抽象工厂" class="header-anchor">#</a> 09.抽象工厂</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>嗯。
好，那我们开始我们呃。
最佳设计模式的抽象工厂模式啊。aspect the factory. 
大家如果呃听了前面的这个车呃工厂方法的话，那再去理解抽象工厂就非常容易了啊，他跟我们工厂方法实际上是同一类模式。
啊，解决的问题都极其类似啊，都是绕开new 的。但是有纤维的小不同。那我们来看一下。
呃，抽象工厂主要面临的变化是什么？是一系列相互依赖的对象的创建工作。啊，对，这儿有个重。
重点啊叫一系列相互依赖的对象。
啊，他就这点不同啊，其他的地方解决问题都是一样的。好，我们来到代码上看看什么叫一系列相互依赖的对象。
首先呢我们假设我们有这样的一个嗯任务啊，就是要写一个数据访问层。
比如在数据访问层呢，你要去创建什么一系列的一些一些对象啊。呃举例来说我们啊访问假设我们访问的是是sq server 的数据库。
啊，那么你需要建立这些数据库的链接啊，然后呢你要去创建这个数据库的命令对象，然后去创建数据库的这个data reader 对象。
这都是跟sql server 相关的。
但是呢。
我们知道数据库呢你做一个存储，那后边呢你一个很有可能有各种各样的数据。
你不光你今天是sql server，可能你过一段时间你的客户希望说我的数据库是oracle 的，或者我的数据库是这个mysql 的，我的数据库是db two 的。
是吧等等，不一而足。那么你这些对应的类型就需要变化，对吧？那我们首先就知道这个new 是不合适的。
对吧，因为你这样一个new 的话，就会把把他们绑定。防死在吃苦shower 上。那这个类的就不适用于面临多种不同数据库的这样一种。
化。
好，那假设我们现在要支持多种数据库呢，大家第一个反应就是说你要支持面向接口的编程，对吧？
你只有做到面向接口的编程的话，你才可以做这个实现我们所谓的多多数据库的这种这种支持啊。好。
那怎么我们在刚才那个基础上去改一下，改进的方案很简单，就是嗯那你需要做一系列的基因基础类，对吧？比如说class。
idb. 
connection. 
这样一个虚基类啊。
当然这个出于演示目的啊，我就不写这个这个鸡肋里边的具体的一些一些呃方法或者属性，或者是一些一些。
这种啊，比如说实际上这个应该是一个啊这个在咱们c e r 里面应该是一个方法调用，对吧？一般来讲样啊就是都是一些。
一些个方法调用。
好，哎，那就大家呃了解这里边就是idb connection 应该有很多很多虚方法。
对吧，然后呢再有呢。
比如idb commander。
是吧面向接口编程。先得把你的接口做出来啊。
然后呢，再有比如说i。
it reader. 
等等啊，就很多这种积累。那我们说像c q connection 啊，就是继承这个idb connection。
是吧所以我我我也把这个写一下，大家了解一下。she got connection. 好，继承public。
是这个idb connection。
去分一下好。
对吧，然后呢当然一样的可以写下很很多啊嗯。
我直接在这填填充了，比如说有还有c q commander 是吧？
还有些人呢？c qde reader. 
还有i 他当然是继承id backman 的，对吧？它集成这些。
就是我先说这是数据库啊。
数据库访问有关的积累。
啊。
对吧这个呢是什么？是咱们。
支持sql server 的相关的类型是吧？那你支持收购自我，当然你要不要支持更多的。
哎，你要要不要去支持这个oracle 也要的是吧？那比如说二十科学下来，然后我把这个sq 所有的这个。
去给他换过来。
当然你还可以去想什么？my s q l d b two 你都可以去写下去啊，时间关系我就不在这里面去去描述这个了。那总而言之就是这里边有支持的很多的变化。
是吧那那你这个。
这个怎么怎么改变呢？这个就是要换成是不是，首先咱们呢。
啊，面向接口编程要求的是什么？就是你要先把你的生命类型换过来，对吧？
idb 卡曼的换过来是吗？然后这边也是一样的，idb 啊这些都换过了。
当换过来，这些是实际上还不够，对吧？你这个new 是有问题的呀。
呃，当然咱们遇到这个问题，马上就想到上节课讲了factory method，对吧？好，那我们就先用代客单侧的看看解这个问题，解决怎么样。
是吧那当然我们也知道啊，你对应的有这个sql connection，你是不是就要对应有这个class。
为了支持你的工厂啊。
factory. 
是吧？
继承一个什么？比如说这个是不是应该也有一个对应的工厂啊，idb. 
connection. 
back 腿。
是吧然后当然它里边的具体的接口我就不写那么那么多了，我就简单写一下这个。
这是一个实际上是一个。
create. 
啊，db connection. 
这样一个方法是吧？呃，当然这这里面其实目前来讲是一个程序函数了。
啊。
好，其他的什么区域呃，虚虚构函数我都不写了啊，大家这个真正你需要做到，你需要完整性，需要补充下来啊，这是他对应的一个类一个工厂是吧？每一个都有这么一个工厂，其实你这个也是的。
啊，这里是不是也应该有一个工厂啊？
你deb come and be a 广场。
that a reader 是不是也要有一个工厂啊，啊，那我们把这个。
嗯，工厂和他对应的生成的类写在一起是吧？
啊，那这个也要写那个卡麦的工厂，把这个connection 给他换成commande 就就可以了。
好。
好像这个之后再把这个换成。
get a reader 啊。
哎。
这跟it reader。
factory. 
啊，然后返回呢就返回这个。
i, i did read. 
创建呢就创建一个。
it reader create the rider. 啊。
好，当然这一些都按照这样一个方式啊，有他的接口，又有他接口对应的。
啊，这个工厂啊，还有我们很明显就看出来这是用工厂方法做的，对吧？create the big connection with the, this comment. 
对的啊啊这个deteriora 啊等等，当然这个。
你这边是不是也要对应的，然后做出来那些东西啊，我们把它也模拟一下public。
然后呢。
是比较有这个。
继承咱们这个i，if the connection factory. 
具体里边我就不写了啊，具体大家自己去怎么new 一个东西，对吧？拿着那个同样的，是不是这个地方也要有啊。
嗯，我们也是具体类和具体工厂写在一起啊嗯这边呢具体类和具体工厂写在一起。
具体类和具体工厂写在一起。
啊，我写在一起是为了帮助大家理解啊，你在实际的开发中间，其实你严格意义上在工程里面应该分成两个不同的文件去写的。啊。好，那这里面是不是把这个。
collection. 
换成commander。
啊。
啊，然后这边呢这个db connection 完成什么it reader。
是吧？cc, that really a factory. and. 
这个然后我在里边就做相关的创建工作啊。
啊，相关的创建工作是哪些呢？是这些这些这些的虚函数的具体的实现。
啊。
那oracle 的话。
类似啊类似我就不写了啊，就是大家从这点上理解，就是说你要支持这样一个工厂，你就要干这么多的事情，对吧？
好，那这边呢？
这边当然就。
需要声明几个类了。
第一呢，你要创建idb connection，是不是要叫要有id connection 的factory？
这样一个指针是吧？
然后呢。
the big connection factor 这样一个指针。
然后要创建这个。
i did come. and 是不是要放i d be commend the factory it。
这样的一个指针啊。
然后这个也完全对比。
i 那个呃reader 是吧，一样的啊。
这代码比较多啊，就是大家不要看晕了。其实你只要思路清晰是吧？你你一定要搞清楚你你现在是在在干什么。
你就你你头脑就不会晕了。三个工厂创建三个对象啊三种对象。好，那这个你有就可以换了，对吧？这个你就被我换成了什么？
b connection are factory. 我们说是一个多态的女友是吧？它底下有一个什么create？
啊。
是不是咱们这个debit connection？
啊。
那这个呢。
一样的是咱们的d b comment。
thank you. 
去创建那个db comment 是吧？
然后咱们这边的这个read reader，其实啊它内部是。
是不需要创建的啊，他内部其实是不需要创建，就他直接会关联。
呃。
当然这里边呃其实有一个呃有一些细节啊，我也是需要补充一下。就是真正啊这边我漏了一个细节，其实呢就是。
他需要做什么？这个卡麦的，你需要执行之前，实际上是需要set 疼你的什么connection？
就就你命令和那个连接是相关的一个对象，对吧？你要下载你的connection，然后十五行这边也是，其实他是秀。
也是相关的啊，卡麦的里边创建出来的一个sql this render，对吧？所以我其实是应该把这句话也也给它拷贝过来了啊。
对。
这就是这里面有相关性。
好。
嗯，那么这样做下来之后啊，当然这个三个就需要在这个构造器里边去去呃去呃初始化它，对吧？
就传一个参数给他。
嗯。
但是那么我们想一想这个类这样的曲线其实要没有要说有没有解决这个目前这个问题啊，其实是啊解决了。
对吧，就是勉强解决，但是他暴露出来有没有其他的问题呢？其实是有的。我们来看一下什么问题啊。
就是大家想一想这个七十行这个地方有可能。
呃，比如说你你如果是做做这个思科支持啊qq server，微软的这个server。
那么你是不是这个地方就是真正传的未来的这个这个factory，就是那个什么c q connection factory。
但是呢你这个db factory 呢，你这个时候能不能传一个oracle 的？
commanded the factory are. 
不可以的，对吧，为什么不可以啊？
就是说你这仨对象必须是同一系列的同组的。
他们有关联性，他们的关联性体现在哪里？大家看看这里其实是有关联性。
啊。
就是我的connection 和什么样的connection 和什么样的commander 搭配，它是有。
你你不能拿一个c q 四。支持智库生物的connection 和一个支持oracle 的commander 去搭配，他肯定报错的，对吧？你统一同理，你也不可能拿一个。
这是commander 的一个就是sql server 的一个commander 创建出一个mysql 的一个一个data render。这也不可以，对吧？这就是他们的体现关联性的地方。
啊，所以大家正确的就是这里面会带来一个紊乱性。就假如未来有人传递。
不同的factory 给你。
就传了一个circle，the connection factory 传递了一个嗯mysql 的commander 给你，然后又传了一个outlook 克的呃，deter or the faculty. 
那就乱了套了是吧？就不同的工厂产生出来的是是不同组的东西搭配不到一起啊，就是八十四行会报错。
二十六号我告诉我当时讲好那么正常的做法，这个这个问题怎么解决啊？这就引出咱们的什么。
abstract factory 啊，我先把它拿出。
烤出来啊，这个这样大家可以回来去对对对比这个几几个代码的演进的过程，迭代的过程啊，我们一直是用那种重构的思路再讲。
讲这个模式的啊，大家来看好，那怎么办呢？
请你想一想。
哎，这个你把他三个分在一起，如果把他们三个放在一起呢。
放到一个工厂里面会不会有对这个问题有改善啊？想象一下，咱们现在有沙工厂是吧？有三个类。
啊，我先把三个类放在一起。
对吧，有三个这样一个类。
打卡实际开发过程中，这个关于数据库访问的还有更多的累啊，有更多的啊。好，然后再把这个。i did the reader 呢。
也给他放过去。
然后呢，这这这这就三个工厂是吧？
那我们说了，你干嘛要三个工厂，如果你这三个都有特别有相关性，这三个类特别有相关性，你是不是可以用一个工厂来创建它？
好，那大家看我就把这个。
三个方法全部塞到一个类。
哎，这样子解决是不是？
想想这个看起来是慢慢感觉很优雅是吧？啊，他们很有相关性，所以我把塞在一起。
高内聚松耦合对吧？如果你是有相关性的，就把合在一起，放在一起。
而如果这个时候这这是生活生活呢也也比较简单了，是吧？那咱们也是同理啊，把这个往上移。
对吧大家有没有发现这个摄影模式一直是在考虑什么？分久必合合久必分是吧？
森禾禾的事情啊。
啊，什么时候拆，什么时候和啊？
需要很多的思考，很多的设计啊，这个时候也是我们把它合在一起。
然后改个名字。
啊，dbf, 当我把这个这沙宣传说拿过去。
会显的饱满一点是吧？
好。
那这个是我继承。day back at. 
那我这个就改改名字了，叫sq。
cb, that's. 
好，这样子已解决。当然oracle 同。
类类类似啊，同理可以那样去做。
那我是不是就可以把这个工厂这边的这个沙工厂合成一个工厂？
是不是？
对呀，把这个换掉。
把这四两去掉，他们要合在一起了是吧，然后改个名字。dbe factory 反映他们的这个合。
我在一起的做法。
好，然后这边是不是？
全部弄成这个了。
这百十。
a, b, comment. 
啊。
但这这边啊其实用x q 的v der 我们就不用去替换那个。
所以大家看到这里的话，你就会发现，唉，这个就保证了他的关联性是吧？因为我是一个工厂，我不可能为同一个工厂实现的时候，我内部不可能再去做一个。
生成一个一个circle 的connection，又生成一个一个嗯oracle 的卡麦呢就不可能了，对吧？我同一个工厂，我就可以确保这些生成的是得到了关联性的保真。
啊。
对，那这个就是咱们的叫做抽象工厂的这个方法啊，我觉得这个名字起的不太好，这个应该叫什么family factory。
好家族工厂啊生产一组是吧？
啊，因为这个咱们呃高for 四位设计模式大师在最早已经定义这样一个做了这样定义了，对吧？那我们就。
不再去计较这个这个名字的这个东西啊，我们回到我们代码里面，嗯，要回到咱们p p t 里面，咱们来看一下啊。
在软件系统中，经常面临着一系列相互依赖的对象。
创建工作。
这就是一系列相互依赖对象的创建工作啊，由于需求的变化，往往存在更多系列对象的创建工作。
澳瑞克是一个系列sql server 是一个系列，my sql 是一个系列等等是吧？如何应对这种变化呢？啊，就是绕开业还是要绕干净啊？
好，那我们来看一下。
提供一个接口，让该接口负责创建一系列相互相关或者相互依赖对象。该接口是什么？
刚才我们的idb factory 就是这个接口。
负责创建一系列对吧？idb connection id be comment. the are are the reader, are the. 无需指定他们的具体类。
好，然后对着这个图啊来再再来看一下。
这里边是不是就很很有感觉了啊？
i expect the factory 是谁啊嗯。
这个是稳定的对吧？首先首先看的是稳定的，然后呢他是谁呢？他就是咱们刚才的idb factory，然后里边那个create a。
create a broke b 就相当于咱们那个create 啊。db collection create dib comment 是吧？然后这边呢abstract。
that a 是谁？
就是咱们的刚才那个相当于这个idb connection，对吧？然后这个fsh act the probe 呢？
相当于咱们呢。
idb commander. 当然这里面只是显示了两个，对吧？你当然也可以有什么spect parc，就相当于咱们刚才那个id this reader 是吧？
然后如果再看具体呢，再来这里。
康create factory 一，咱们先来看这边啊。好吧，那就啊算了，先说完这个好了，呃，concrete factory 一相当于咱们呢。
蛇口收啊，对吧？circle, they big connection. 呃，这db factory，然后这个create table product 的a 啊，相当于咱们the creator create 那个。
啊，呃呃the big collection 对吧？那么里边对应的这个product a 是谁呢？
啊，这个呃实实际上是这点啊，大家注意看啊，这个一一对应的啊a 这个product ae 是谁呢？
注意这条这条虚线啊，prae 就是咱们的c q。
db connection 是吧？for that, the b e 是是是咱们的什么c q o d b commander 啊。
然后当然你这边product t a 二是什么呢？相当于咱们的呃这个。
刚才说的哪个呀，就是那个oracle 是oracle 的。
呃，这个db collection。
那然后这个这个我我我给你画画个不同一点的颜色，好吧。
嗯，那个绿色吧来表示另外一组变化啊。
啊，这个绿色主主系的啊。
就是咱们的oracle。
另外一种变化啊，project a 二啊，相当于咱们的oracle 的db connection，the project b 二相当于咱们oracle 的。
db comment. 
啊，然后这个。
康create factory 二就相当于咱们oracle 的。
db 啊factory 是吧？
这样是可以看的很清楚啊，所以红色表示稳定的蓝色表示第一种变化，绿色表示第二种变化。
啊，咱们设计模式的图书是啊g u f 定义的这个图。有的时候他给你变化，有一套是给你一种变化，有些地方他给你的两种变化啊，咱们用这个不同颜色来区分开来。
这样的话大家在看这幅图啊，对着代码这个代码去梳理，对吧？你你就能够啊看几幅图就会特别明白了。
好，最后做一个总结，如果没有应对啊，多对象，我们换一个颜色，换成红色啊，多系列对象。
需求变化则没有必要使用factory 啊，这个时候使用简单的这种工厂方法完全是可以的。
所以公呃抽象工厂的核心是解决什么系列对象啊，系列对象指的是什么呢？在某一个特定系列下的对象之间，他有相互依赖或者作用的关系。
不同系列对象之间不能相互依赖。就是咱们刚才讲的你你你生过之后的啊connection 不能和oracle 的combine and 去去去依赖，对吧？
去关联。
呃，那and strict，or are factory 模式主要在于应对吸系列的需求变动。
啊，他的缺点在于难以应对新对象的需求变动。啊，这个解释一下。
就是说你可以给这个加一个新的系列也很好，对吧？比如说你支持收购server，你这是oracle，你在支持db two，支持my s q l 都可以。
但是呢你如果在加一个新对象的话，比如要在这个这个类内去加的话，就不合适了。为什么？这是一个抽象基类，抽象基类是什么要求稳定的？
对吧，当然有些朋友说，哎，这个老师真的是这个这个模式没有缺点。
我也告诉大家，任何一个模式都有缺点。我们强调那个模式的稳定的部分就是他的缺点。你如果假设那个稳定的部分变化了，那个模式就不适用了。
对吧就是你你假设这个地方在变化，对吧？当然有些朋友说a 料是我讲还是这个地方变化怎么办？
啊，那我告诉你这个模式不适用，有其他模式也许可以去补足这个问题，但你一会儿又假设，哎那个那个地方变化怎么办？呃，如果你极端的假设任何一个地方都变化啊。
告诉大家，没有什么模式，没有任何一个模式或者几个模式合起来，可以解决你的问题。那就你不能推导到一个极端啊，极端情况就是你所有地方都在变化。
那么你你没有任何模式可以解决你的问题。反过来说啊，你所有地方都稳定。有些朋友说我这个文件这个稳定我都没有多系列的变化那个等等这些东西。
那我们说这个时候你还干嘛用模式呢，对吧？直接写就可以了啊，设计模式是解决什么稳定中有变化的这种场景。
这是咱们的常态啊，这是咱们在软件工程领域遇到的常态啊，软件功能里面很难走向两个极端。一个极端是没有任何一个地方的变化。
啊，一个地方是没有任何一个地方，这就所有地方都在变化，一个是所有地方都都是稳定的，我们的所有地方都变化没有。
呃，这没办法使用摄影模式，任何一个模式都解决不了你的问题啊，但是呃如果所有地方都稳定，你你就没有必要用用模式了。
啊。
好，那。
还是get factory 这个模式呢，其实大家也可以体会一下啊，他他跟工厂方法模式实际上是。
很接近，甚至我们可以说工厂方法模式是fsh factory 的一个特例。什么特例呢？大家想想我这边要创建杀对象，我要用啊抽象工厂。
我那边如果只创建一个对象，他不就是工厂方法嘛，对吧？就是这样，所以大家可以吧，那么就有些地方直接都把工厂。
方法和抽象工厂直接就叫什么工厂模式啊，指的就是他可能是抽象工厂，也可能是工厂方法啊，就是他两个的区分度没有那么那么的明显。
好，那我们今天的这个工厂方案啊，抽象工厂设计模式就讲到这里啊，谢谢大家。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br><span class="line-number">177</span><br><span class="line-number">178</span><br><span class="line-number">179</span><br><span class="line-number">180</span><br><span class="line-number">181</span><br><span class="line-number">182</span><br><span class="line-number">183</span><br><span class="line-number">184</span><br><span class="line-number">185</span><br><span class="line-number">186</span><br><span class="line-number">187</span><br><span class="line-number">188</span><br><span class="line-number">189</span><br><span class="line-number">190</span><br><span class="line-number">191</span><br><span class="line-number">192</span><br><span class="line-number">193</span><br><span class="line-number">194</span><br><span class="line-number">195</span><br><span class="line-number">196</span><br><span class="line-number">197</span><br><span class="line-number">198</span><br><span class="line-number">199</span><br><span class="line-number">200</span><br><span class="line-number">201</span><br><span class="line-number">202</span><br><span class="line-number">203</span><br><span class="line-number">204</span><br><span class="line-number">205</span><br><span class="line-number">206</span><br><span class="line-number">207</span><br><span class="line-number">208</span><br><span class="line-number">209</span><br><span class="line-number">210</span><br><span class="line-number">211</span><br><span class="line-number">212</span><br><span class="line-number">213</span><br><span class="line-number">214</span><br><span class="line-number">215</span><br><span class="line-number">216</span><br><span class="line-number">217</span><br><span class="line-number">218</span><br><span class="line-number">219</span><br><span class="line-number">220</span><br><span class="line-number">221</span><br><span class="line-number">222</span><br><span class="line-number">223</span><br><span class="line-number">224</span><br><span class="line-number">225</span><br><span class="line-number">226</span><br><span class="line-number">227</span><br><span class="line-number">228</span><br><span class="line-number">229</span><br><span class="line-number">230</span><br><span class="line-number">231</span><br><span class="line-number">232</span><br><span class="line-number">233</span><br><span class="line-number">234</span><br><span class="line-number">235</span><br><span class="line-number">236</span><br><span class="line-number">237</span><br><span class="line-number">238</span><br><span class="line-number">239</span><br><span class="line-number">240</span><br><span class="line-number">241</span><br><span class="line-number">242</span><br><span class="line-number">243</span><br><span class="line-number">244</span><br><span class="line-number">245</span><br><span class="line-number">246</span><br><span class="line-number">247</span><br><span class="line-number">248</span><br><span class="line-number">249</span><br><span class="line-number">250</span><br><span class="line-number">251</span><br><span class="line-number">252</span><br><span class="line-number">253</span><br><span class="line-number">254</span><br><span class="line-number">255</span><br><span class="line-number">256</span><br><span class="line-number">257</span><br><span class="line-number">258</span><br><span class="line-number">259</span><br><span class="line-number">260</span><br><span class="line-number">261</span><br><span class="line-number">262</span><br><span class="line-number">263</span><br><span class="line-number">264</span><br><span class="line-number">265</span><br><span class="line-number">266</span><br><span class="line-number">267</span><br><span class="line-number">268</span><br><span class="line-number">269</span><br><span class="line-number">270</span><br><span class="line-number">271</span><br><span class="line-number">272</span><br><span class="line-number">273</span><br><span class="line-number">274</span><br></div></div><h2 id="_10-原型模式"><a href="#_10-原型模式" class="header-anchor">#</a> 10.原型模式</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>好，大家好，那我们下面开始我们c 加压设计模式，prototype 原型模式啊。
呃，原型模式仍然属于我们对象创建模式的一种。那大家在前面如果了解了咱们这个啊fact msd 和abstract factory 的话。
那么其实应该来说，前两个模式非常的popular，而用的比较多。那后边的prototype 和builder 模式呢用的相对比较少啊。
呃，也比较简单，比较容易理解。所以我们会讲的时候，我们会稍微快一些啊，我首先来看一下，不过都太不这个模式呢。
呃，他解决的问题啊跟咱们这个faker method 是一一模一样的问题啊，也是有一点点细微的不同，它也是一个。
我们说fake nice 的一个变体形式。
怎么变呢？我们首先首先先抛开这个这个动机啊，就是我们不谈，我们直接直接跑到我们这个fx msd。我在这里呢把上节课啊。
咱们的代码呢拷贝过来。
嗯。
咱们哪些代码呢？我们首先来看一下我们上节课啊走到了。
这里和这里对吧？
好。
呃，我们当时做工厂模式啊，最典型的就是这是抽象类。
这是针对的具体类，这是工厂的抽象的那样一个工厂的积累。这边是具体的工程，对吧？
那么原型模式呢做了一个嗯花招啊，耍了一个小小花招，怎么耍呢？大家来看啊。
把这两个类呢。
合并起来。
就我把这两个类合二为一的。
呃，现在看起来很奇怪啊。
对吧，就是我们我们之前讲课一直在讲分离，分离就是说呃分离责任。分离职责是你设计设计啊里面非常重要的一个一个一个环节。
但是我现在为什么分了之后，我们又把它合并，对吧？好，我们当然合并会有，待会再讲礼，我们先来看合并是咋核的啊。
之后当然咱就名字都叫slater。好了，就不需要这个需呃学习构函数，当然不需要了，对吧？
啊，那就这个方法呢往上放。
那这个方法呢，我起一个名字叫不用这个create slater 了。
啊，我起个别的名字，这个方案叫什么名字呢？我叫克隆。
对，好，克隆克隆谁呢？克隆自己对吧？克隆所谓克隆就是克隆自己。
它实际上也是一种创建，但是是一种特殊的创建。呃，就是我们这里讲的通过什么我来加个注释啊。
通过克隆自己。
来创建对象。
克隆自己来创建对象啊。
好，那有了这样的一个东西之后呢，大家来看这边怎么办？
那这边实现的时候就不是这样子了。
啊，其实其实就不是那样的，而是啊我们来也是把它翻译过去啊。
啊，这个东西。
往上搬。
翻到这里。
咱们来看看这个具体实现啊，这边就变成一个克隆的方法，是吧？
然后这个克隆呢？
这时候怎么克隆一个对象？
大家想一下啊，你比如说binary 克隆自己，怎么可能自己啊。
在cdr 里面有了最成熟的克隆自己，所以这个克隆是深克隆啊，最最成熟的克隆自己的方法叫做什么拷贝构造函数啊。
对吧？
那这个拷贝之后还是怎么调用啊，是不是这样调用？你有一个band is later，然后括弧拷贝构造自己。
啊，自己就是当前的this 啊，这是当然因为是个指针了，所以我们需要加这个型号节饮用。好，那这样做就是一个。
万泉的做法对吧？实际上底下的这些东西，这些类型呢都可以这么干。
啊。
啊，这个也可以这样放。
当然这个类名要要要起个不一样的类名，是吧？
为明这边是new tax plate。
这当然有一个前提是什么？
就是你那个类的拷贝构造函数得写正确。
是吧？
这这个咱们其他的c e r 课程里面就有讲啊我们这个设计模式课程就不谈这个拷贝构造函数了啊，所以你的拷贝构造函数必须写正确，你这样才才克龙政权。
啊，好，当然这些具体工厂还有没有必要要了，没有必要要了，对吧？
啊。
这个模式就变体变到这里了。
啊，然后呢，真正那个地方怎么怎么用呢？我们来看看没form 怎么用啊。
咱们来来到这里。
是是这个梅方沐二是吧？
啊，这个地方本来是放了一个factory，现在应该也放这个什么i s later。
对吧？
这个地方我们起一个名字叫葡萄time。
啊，这就是一个原型对象。
我拿着这个圆形对象。
所以我在这里面要传递是吧？
啊，i s later. 
这样一个接口。
那在这里呢？
我们有有些朋友说，哎，在这里好了，拿着这个prototype。
直接在这儿用了。
不用再这么干了。
这这做法对不对？这做我肯定不是不对的啊，为什么？
因为。
这个原型对象只是放在那宫颈去克隆呢啊真正使用的时候要创建出新的对象。既简单说我们八乘一可以可每一次。
弄完之后要创建新对象。
啊，不能一直用这个原型对象啊，用这个原型对象是不是公共使用的原型对象，就是放那儿就供你克隆的，你不能直接拿着原型对象就用。
那就违背了原因这样设计模式的这样一个一个宗旨。那应该怎么用呢？应该是这样子，对吧？再回来啊。
还是。
这个prototype。
拿着这个prototype。
然后在上面。
去调用克隆方法。
好，那我就通过克隆啊。
克隆原型。
得到了一个新对象。
是吧得到一个新对象，就十三行这个对象，那这个对象我就可以对他进行split。
啊。
对吧那么。
来看一看啊，这里注意这个原型对象放在那儿。
不能不能使用，只能去可能啊，这个就是咱们原型设计模式。
啊。
大家看是不是就是我我刚才写一样的说法，就是把什么把工厂方法那个模式里边。
两个对吧？一个是工厂抽象的积累和啊这个具体的业务的抽象类给它合并了啊，但是这个问题不是合并这么简。
三对吧，就是说嗯那为什么要合并呢？
啊，为什么要就是这样去做解决的嗯抽象公呃抽象方法所所不适合解决哪一类问题呢？
好，我们来回到p p t 来看一下啊，就会比较了解这个问题。
嗯，我们把这个播放器。
我们讲的在软件系统中啊，经常面临着某些结构比较复杂的对象。
啊，结构比较复杂。
对象的创建工作。
由于需求变化啊，也是啊这个这个这些对象面临的剧烈的变化，让他们去去拥有比较稳定一致的接口。
那如何应对这种变化呢？啊，那我们原型给出的解决方案，使用圆形实力。
啊，这个圆形实力就是咱们刚才。
刚才那个prototype 对吧？
指定创建对象的种类，就我这个prototype 就是你将来要用的对象。然后呢，怎么创建呢？通过拷贝。
这是克隆，这里注意是深克隆，而此前克隆前可能会带来问题的。你浅克隆什么问题啊？你会把原型对象的状态会改变的，对吧？
那么实际上是通过深刻了啊这些对啊原型来创建新的对象。
对这个创建新的对象，就每一次。
啊，每一次这个button click 的时候。
对吧我们呃再来再来看一下，咱们刚才没form 二这里啊每一次当button day click 的时候都会创建新的对象，这个splatter 都是一个新的对象。
一样的，我这里边也没有考虑内存管理的问题啊，实际上正确的做法，你你是需要在十八行这个后边去啊处理这个指针的，对吧？这个指责。
好，那么我们再回来。
来看一下这个类图啊，这图也很简单，对吧？那么这个。
是prototype 了。
没有。
啊，这个就是可以被克隆的那样。那个他底下有一个克隆方法是吧？
嗯，然后呢，你这个具体的类型啊。
那我们把它换一个颜色。
具体啊不同的类型，比如说这个就相当于咱们刚才的什么什么嗯。binary is later 啊。
啊，这个我都给他换成蓝色的啊。
banners later 或者是那个嗯啊videos state texas state 是吧？不同类型你实现自己不同的克隆方法啊，当然如果。
嗯，你有这个。
有的时候一一般来讲这个proto type 里面应该像像我们刚才有一些play 的方法，对吧？你不见得就是全都是只是放一个克隆方法，也也太太不合适了，是吧？
这是一个非常概要性的人。荼毒誓啊。
对，这关键就是底下这里return 自己是吧，为return 一个拷贝自己。
那么看着呢客户端。
啊，或者这个使用你的客户程序啊，就是咱们的misinform，对吧？这个kant 相当于咱们的民营form。雷锋，我们怎么用你呢？每次用的时候就是克隆一下，每次问一下就克隆一下。
那我们刚才说的那个问题，现在大家对结构，对整个这个已经比较了解了。那那就是我我们再回来，就是说那么什么时候要用这个克隆啊？
他跟f 换句话说，他跟fact the method 最大区别在于面积占。
所以在这句话就是某些结构复杂的对象啊。
简单来说啊，以前呢如果你用这个工厂方法的时候呢。
你其实是一个嗯呃比如说用工厂化去new 一个一个一个简单的对象是吧？哎，就够用了。但是现在呢我们说当这个对象比较负。
复杂的时候。
通常呢你发现他的初始状态呢又不是正对应呃呃最想用的那个那个对象啊。这个时候呢。
实际上反倒是说你有一个对象，他已经达到一个某一个比较好的状态的时候呢，你去调用一些他这样一个考的构造函数，就是深克隆的方式。
把他对象当前的这个状态给他取出来。
这样就达到了一个比较好的，就是如果大家想你这个对象结构比较复杂，你那个factory method 就是那个工厂方法是不是要写的很。
还有很烦，很复杂啊，甚至都在某些状态底下都写不正确啊。但是这个原型呢就有这样一个灵活性啊，圆形的灵活性就是说。
我只要我这个原型，未来的这个原型定好啊，他的一个状态就在咱们这里啊。
我传入的状态是什么？
就这个传入的这个prototype 的状态是什么？以后你克隆出来的就是我的那个状态。
是这样，就避免了用f ms 的去做的时候，你的那个状态过于复杂，实现起来不好实现啊不方便实现。
但是呢我们这边呢就是只要实现一次以后就克隆他，克隆他就好了，是吧？
这就是当然呃什么叫结构复杂是吧，这个这个界定没人没人有一个特别公允的界定。
啊，简单来说什么时候使用原型？
设计模式什么时候使用反fk method 的设计模式，最大的这个区分点就在于你用工厂方法模式创建对象是不是非常简单的几步骤，就可以把这个对象。
创建出来还是说你需要考虑对象的很复杂的一个中间状态啊，然后你又希望保留那个中间状态。如果是后者的话，那么你就永远幸。
啊，那也也因此啊，大家看圆形的这个设计模式啊，它解决的问题啊和咱们faction ms 的解决都是一模一样的。
都是什么都是new 的问题。
对吧，就是其实都是这个new new 的问题啊，但是呢。
他解决有一个有一稍微特殊点特性啊，就是咱们的这个比较对象比较复杂。
那么这种情况呢，坦白来说，在在开发中间比较少，不是很多啊不是很多。所以呢原型在咱们真正实际应用过程中呢。
就是你以后在这个工作中啊，实际的项目中间建造的情况不是很多。但是呢你见到要认识他，要知道这种技巧。
是吧他他为什么要用这个而不用fx method？
好，最后做一个总结prototype 模式我们同样用于隔离类对象的使用者和具体类型之间的耦合关系。啊，就是那个new 对吧？你。
我我用你，我一定要用你有吗？不一定是吧，我们说啊那么用一个多态的方式来创建啊，它同样要求这些异变内拥有稳定的接口。
嗯，这是这是跟fex master 一样的地方啊，他这个麦手的不一样的地方在于什么？这个原型模式对于如何创建易变类的实体对象采用的是什么？
原型克隆的做法。
他使得我们可以非常灵活的创建啊。
啊，灵活的创建这个。
啊，我拿这个笔勾一下。
某拥有某些稳定接口，注意，这是一个前提啊。你得拥有稳定接口。
对，就是你们的sweeter 的接口的问题，因为这个不稳定的，最后我这个全盘结束，对吧？所需工作仅仅是注册一个新类的对象。
也就是原型，然后在任何需要的地方就克隆就可以了。
但一般意义上啊，在咱们c 一家典型的对象模型里边呢，你可以用这个呃就是拷贝构造函数。只要你的卡不够，到时写的正确的话，这个克隆方法一般都是。
嗯，绝对是没有问题的，对吧？但是呢在某些语言里边啊，比如说像在家啊或者c shup 啊一些一些高级语言里面呢，它的深克隆。
跟跟c 加的深克隆的写法有些不一样。也就是说简单来讲那些语言没有没有那个拷贝歌的函数啊，那这个时候呢他有时候会需要利用一些。
框架里边的有些是序列化的方式啊，就是正在内存流里面做一个序列化，再做一个反序列化啊，cdr 这种做法很少啊，因为c 一家r 做个。
做虚化也不是那么容易的啊，需要很多框架的搭配啊，但cgi 因为有一个便利的条件，就是这个拷贝构造函数啊，一般是自己家里面一个标配了。
大家用这个卡被疙瘩函数来做原型就就很好了啊。
好，那prototype 这个模式，我们说它是一个小模式啊，用的也不是特别多的模式啊，它是一他也是一个factors c 模式的一个变体形式。
我们今天就这个put temp 就讲到这里。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br></div></div><h2 id="_11-构建器"><a href="#_11-构建器" class="header-anchor">#</a> 11.构建器</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>好，大家好，那我们开始我们c 家设计模式的。
有点模式啊构建器。
呃，构建器也是属于咱们对象创建模式的其中的一个啊也是一个比较。
呃，不那么常用啊，比较小小的一个模式，我们来看一下构建其他解决的问题。
在软件系统中啊，有时候面临着一个也是对象比较低，比较复杂啊。
给一个复杂对象的创建工作。那通常由各个部分的子对象用一定的算法构成啊。
由于需求的变化呢，这个复杂对象的各个部分经常面临着剧烈的变化。但是将他们组合在一起的地方。
这个算法呢却相对稳定。
所以这里有两个关键词，一个是变化，一个是稳定。
对吧，就是他有一部分是变化的，有一部分是稳定的。
啊，而且就是他是在一个算法流程里面，当然看到这段也有没有想起来我似曾相识啊。我们在哪个模式里面遇到我这个。
很像啊。
template method 对吧？模板方法模式啊。
但这个模式呢builder 模式呢比较稍微特殊一点，它主要是解决对象的创建工作。
那我们来看一下对象创建工作是吧？
呃，在哪些地方稍稍特殊一点啊，我们来举个例子啊，回到代码，举一个例子。
同样呢，我们在这里也是啊打开这。
找找我们的。
有点儿。
想的好，那这个就是说假设我们现在要在比如说一个游戏里面的场景啊。
我们的游戏里面，比如说我们要建房子。
啊，那我们这个有不同，可能建一些茅草屋，也是房子才能建一些砖瓦房，是吧？可能建一些特别豪华的一些。
啊，一些一些房子啊，就各种房子了啊，但是我们知道建房子你固定几个流程主要干的对吧？底下这个地板地基地基地板。
四、四面墙壁窗户房顶对吧？这是你逃不掉的啊，还有我们对吧？而且这个流程相对是固定的。
但是呢具体里边，比如说这个不同的房子，可能天花板不一样，建造的方法不一样，不同的房子的窗户构造方法不一样，门的。
方式不一样是吧？
所以呢我们在这里就是说。
嗯，比如说构建假说，构建窗户门啊，天花板是几个步骤啊，是。
他他一他他阿尔帕的三对吧，等等。然后呢，构造整个啊房子的流程呢，比如说是这样子的。
那我们先构造pe，然后比如说开四开四面窗户啊，然后构造这个判断某些变量啊，然后的结果然后再来看是不是要做这个事情。
啊，等等啊呃他是一个固定的流程啊，那我们现在的问题是。
呃，每一个子步骤构建，此步骤是变化的。所以我们把它实现成虚函数，这里就是纯虚函数啊，然后呢具体里边的。
嗯，整个构建的这个流程呢又是稳定的，我们把它放到一个算法结构里。这样写下来，很多朋友会发现哦，真的很像他们开的买手的，是吧？
确实非想象啊。
那么。
我们在思考下这个问题啊，有些朋友首先我这里面提第一个问题，就既然是构建这是构造一个对象，对吧？能不能这样放，能不能把它写成这个。
构造函数啊。
对吧那写成house 这样一个构造。
首先呢不能的啊，大家知道在c 加加里面啊，这个cce 家里面比较特殊，c 加加里面的构造函数里面如果去掉虚函数的话，它实际上是完成的是什么？
静态绑定。
啊，他不是动态吧。
啊。
呃，简单的说，这行话应该第七行应该是调用哪里调用这个标志pae 的史前，但这儿又没实现。这个其实就是报汇报错了。
对吧如果他就是说他不会去调用子类啊，在构造函数给他虚函数是不可以去调用此类的那个去函数的。
那个over wright 的版本。
啊。
嗯，至于为什么？
我这简单说一下理由，以后大家有机可以深入的去了解啊，这个实际上是c 家对象构造模型里面。呃，你就是说你的子类的构造函数是先调用你父类的高德函数的。
吧，呃如果大家想如果允许掉这个这个构造函数，呃，如果允许这个实现是动态绑定的话，那么子类的构造函数要先调用这个。
house 的构造函数。那这个构造函数去调用，反过来去调用子类的那个区函数的o r y 的版本的话，就会导致一个结果是什么？你的子类的构造函数我还没有完成还没有完成呢。你子类的渲染树先被吊。
有了。
啊，这违背一个对象的基本伦理吧，对象的基本伦理是什么？你得先生下来，对吧？过段函数你诞生过程啊，你得先收下来，然后你才能什么。
发挥行驶行为。你不能是说你你先行使行为，对吧？还没还没还没生下来呢，你现在要去就行驶行为啊，这也这就是cdr 之所以这么干的一个原因。
啊，呃但是其他语言不是这么啊，比如说像讲啊，其实shop 里面这个都是动态绑定，就在构造函数里面调用这个方法是ok 的啊。但在自己家里面咱们不ok。
所以呢这里面不能写成塞到构造函数里。
如果可以sf 的还是不一样，当然最好放在过道还是什么就就很很舒服了，对吧？那不能放到棺材上面，就要放一个特殊的函数。比如说我们这儿放一个i n i t。
啊，这个i l i t 呢就是一个初始化啊那么。
接下来呢比如说我在构造一些一些一些具体的啊，比如说石头房的stone house。
那我去继承我的这个house。
啊。
然后呢。
在这里。
就是去override 这些具体的区函数是吧？
一样的，我们也是把它推荐，把它设置成protected，对吧？是因为大家知道原因吧，因为你这个单个步骤没啥意义，对吧？
你三个步骤被外界调用的画面含义。
这个去做一个over right 啊，当然你有石头房子，你也可以有什么这个水晶房子是吧？你可以可以有一些茅草房子，哎，那个各种啊。
好，那要说啊丢了的模式，其实你做到这儿已经ok 了，对吧？已经是完成了我们这个。
所以builder 模式在这样一个宗旨啊，我们先来看一下。
怎么解决这个问题，对吧？就不断模式的定义什么将一个复杂对象的构建逾期表示相分离。
使得同样的构建过程可以创建不同的表示。
这就是同一个构建过程。
啊，以后呢，你这个石头房子你就偶尔来的这这些对吧？你的茅草房牛耳的那些，但是你的构建过程是一样。
对吧你的构建过程是一样的啊，那我真正我要去用你的时候怎么去用呢？嗯，比如说。
那我就呃house。
这样一个批号是指针，对吧？等于new。
don't off. 
对，然后p house。
调用这个ini t 是吧，我就完成了我这样的一个这样一个构建，是不是？
这就完成了。
嗯，但是呢有的情况下做到这儿。
还有优化的空间。
什么样的空间呢？首先来说啊。
就割断模式呢，就是说在某些场景下呢，可能你这个对象就是过于复杂。
这样会复杂呢嗯除了实现这些之外，你对象还有其他很多方法，很多字段，很多属性，对吧？行为跟他搅在一起呢，有的时候呢他。
哎，大家觉得可能不太合适，就是会会会做这样一个拆分啊。
还怎么拆呢？
这部拆分啊。
可以拆，可以补全。坦白来说啊，比如说我这里面再有一个house。
director. 
这个类。
其实就是把这个i i t 啊这个整个初始化的这个东西呢。
给他拆出去。
猜到这里。
啊。
好，然后呢。
他的里边塞一个house builder 这样一个指针。
啊。
up back. 好好。
builder. 
pos builder. 
这样一个指针。然后当然在这个过程中呢，就把这个zs 给他换成p e house，有点是吧？
反正这个这个唤颜也很简单，对吧？
那么这个就直接写个看。you can strike. 
这样一个过程。
呃。
当然这个construct 的话，你你仍然是可以。嗯，比如说有一个呃一个返回值，对吧？哎，举例来说这里边。
为什么q house 是吧？
好。
然后。
那最后呢在这儿。
britten 谁呢？t house 十。
啊，builder, 然后呢get a result 是吧，就直接返回去。
那这个就可以成为一个稳定的东西。host director 就是永远就是这个样子了，是吧？
啊，那以后呢想重写的时候呢，怎么就就重写这个house builder？
啊。
当然很多时候可能是说又有什么样的house。
啊。
就是这俩都是都是都是抽象激烈，对吧？耗时也是抽样鸡肋啊，然后就是hospital 也穿进来，然后你有自动house 啊去重写它也要。
风险具有东house builder。啊，就是就是一一对应啊。
通过这样的一个方式啊，我把这个简单写一下吧。
对啊。
呃，这个地方要有一个抽象积累是吧？
然后呢再来一个啊。
就是stone house building。
呃。
对。don't of you. 
他继承这个抽奖积累啊。
哎。so how the stone house builder 啊。
house, how, how to builder. 然后在host director 啊，就永远负责这个事情。
那以后当然就更需要做事情的时候就就怎么样，你你肯定需要一个一个构造函数吧。
这个具体的构造函数就是去负责实例化。这个号是嗯house builder，对吧？就给你什么样的house builder 啊，我在这再写一下。
你以后就会创建出什么样的house。
对吧？
呃，当然这么绕来绕去啊，咱们做了好几种变体，对吧？绕来绕去，万变不离其宗的是大家。
要理解谁是稳定的形式变化。简单来说，这也是我们说马丁福勒的这个重构里面讲一个不能。
不能太有太肥的类，对吧？啊，所以所以一个一个很胖的类啊，你这个类的代码行为如果太多啊就不太好，需要重构，对吧？
啊，就是说你的这个构建过程竟然如此之复杂，所以需要把这个构建过程呢提取出来，变成一个单独的类的行为。
这个时候大家一般的情况下会怎么做呢？
会把这个类拆分啊就耗时这个类拆分一部分是这个本身这个类另一部呃是呃就累的状态和行为，另一部分就是类专门做构建的那个部分。
啊，我们做一个简单的拆分。假设现在啊有这么两个，一个是class house。
啊，哒哒哒哒啊，我就不具体不写了啊，就是你那些窗户门什么乱七八糟的各种行为啊，然后呢，再整一个什么。
好builder。
啊，这号被盗就放在这里了。好，然后呢，这个地方呢？
塞一个号是指针啊。
对。
当然这个他们两个类的关系啊，或者放上内部类的方式，或者放成有缘的方式来定位。就是你要使的housebuilder 能够去很方便的访问到house 里面的成员。
啊，然后在这里面呢具体去构建的时候就变成了什么应该这样一种构建方式。
我可以呢。
嗯。
我在build 的过程中啊。
我实际上会把这个批号是指针啊，就build part，一直都排到二内部啊啊这个其实也是有必要方成一个。
protected 嗯。
放上炮台。
这这内部要去使用这个p。
house. 
这个指针。
啊，他的比如说window 啊。
等等等，那怎么样啊，就类似这样的语句啊，就是你要去在每一个地方去访问你的t house。
当然这个如果更更那个什么的话，就写成part 一吧啊。
要做那些事情。
对，就是这样子的一种一种方式啊，那么。
使得呢我们在构建这个的这样的一个过程。
大家会发现啊，你这把皓齿和house 是builder。
给他相分离。
好，那。
这样做了之后呢。
那具体你再去啊实现的时候呢，哎你可以有一个比如说get result 啊，假设在这里面，比如说有一个。
void 啊，这个实际上是一个吸构函数。
你说house。
该车。
result. 
return 这个p house。
啊，先把这个指针在在返回出去啊，外界就能拿到你这个职称啊啊那这就是这个house builder。
啊，所做的事情就好。斯为的专管构建啊啊house 呢给他扔出去啊，分离开来。
他当然这样做其实已经够了。那但是呢有些人觉得不放心，这些人呢会做一些觉得哎既然这个物是稳定的。
这个部分是稳定的。
那我能不能？
再干一个事情啊，把这个东西呢再往外拆啊啊有些人啊啊这个时候你你这样这样做，就是用这个host director。
啊。
让他来做了。
啊，这这边我我就不写了啊，不去了啊。直接知道就是host 德尔看你去初始化一个某一个，比如说stm house 有点你构造出来那个house 就是一个stone house。
啊，如果你塞一个是呃比如茅草五的一个一个标点，你构造出来就是茅草屋的一个house。
对，那这个这个面还是这块我可以选码去掉。对，就这样一个过程。
好，那有了这这这个是所谓啊比较完整的或者演化而做了几个演化之后的这样一个。
有一个版本啊，但是呢大家回到最初的那个版本，其实也ok 啊。你并不比说一定要实现这么复杂的一个版本。这个复杂版本最大的几个考虑啊，第一呢就是。
让这个。
大家可以看一下这里的一个说法，就将对象的表示和构建相分离。
什么号是对象的，表示house builder 是对象的构建相分离啊。
呃，然后使得同样的构建过程可以什么创建不同的表示。
同样的构建过程就是就是在这里啊，这个这个注意不是虚函数，对吧？这个是一个普通的函数，它是稳定的啊稳定的。然后呢里边。
这些塞入不同的这个指针，那就构造出来是不一样。
好，那我们回到p p t 来对应咱们这个slice 里面。
呃，这里边也是啊，咱们有几个部分，对吧？哪些是稳定的？
整个这个部分都是稳定的啊director 对吧？就相当于咱们刚才那个house direct。
这边有个builder 啊，相当于咱们的那个什么。
house builder 啊就是抽象基类，其实还有一个product。
讲一个抽象的product 和具体的product。
啊，那么据这里面没画出来啊，我们就看只看那个好啊，具体的那个builder，具体作者就是在我们蓝色的部分。
啊。
蓝色不？
对，这这就是我们这个builder 模式的一个类图的形式。我们也强调了这只是一种演化的可能性。
其实呢这个director 和builder 呢其实是可以就你在某些时候你合并也没什么，对吧？这主要看你还是看你的类的复杂度啊。
就是原则啊，什么累，越来越复杂，就拆迁拆拆拆拆对吧？类越来越简单，就合并合并合并啊，这这这是一个普通。
变的重构原则啊。
好，最后做一个总结。builder 模式主要用于分步骤，构建一个复杂的对象。在这起步骤是一个什么稳定的算法。
啊。
还是要强调啊谁是稳定的啊，谁是变化的。而各个复杂对象的各个部部分经常变化。
对吧，就像我们说的一个房子的整体流程是稳定的，房子的各个部分窗户门啊，这些构造过程是变化的。
变化点在哪里，封装在哪里啊？标段模式主要应对什么，复杂对象各个部分的频繁需求变动，其缺点在于难以应对分步骤构建。
算法的需求变动就是那个const struct 要是稳定了啊。
啊，当然有的朋友会说，康sir 如果不稳定怎么办？把它整成虚函数，继续整他的子类，对吧？但是渲染树也有要求稳定的部分啊，渲染入不是所有的变化的。
悬殊的要求什么参数稳定返回至稳定，对吧？你不能参数也变，纺织也别。
如果你参数也变，房子也变，怎么办呢？参数再弄鸡肋之类是吧？再按一下这个病啊，这是我说的，你总能从变化中也找到稳定的，你就可以用设计模式了。
你如果变化里面找不出稳定的，那对不起，没有哪个摄影模式可以满足你啊。
好，那需要注意的语言的具体的语言不同啊，在builder 模式里面呢，不同语言构造期内啊，调用虚函数是有差别的啊，这是我们讲的cg 里面是不能直接调选书的这。
是部分的原因啊，咱们要把标在移出去的原因。
呃，但是在c sharp 或者java 这样一些其他语言在构造前面调用循环数是ok 的啊。
好，那这种模式也是一个小小的模式啊，我们今天就讲到这里。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br><span class="line-number">177</span><br><span class="line-number">178</span><br><span class="line-number">179</span><br><span class="line-number">180</span><br><span class="line-number">181</span><br><span class="line-number">182</span><br><span class="line-number">183</span><br><span class="line-number">184</span><br><span class="line-number">185</span><br><span class="line-number">186</span><br><span class="line-number">187</span><br><span class="line-number">188</span><br><span class="line-number">189</span><br><span class="line-number">190</span><br><span class="line-number">191</span><br><span class="line-number">192</span><br><span class="line-number">193</span><br><span class="line-number">194</span><br><span class="line-number">195</span><br><span class="line-number">196</span><br><span class="line-number">197</span><br><span class="line-number">198</span><br><span class="line-number">199</span><br><span class="line-number">200</span><br><span class="line-number">201</span><br><span class="line-number">202</span><br><span class="line-number">203</span><br><span class="line-number">204</span><br><span class="line-number">205</span><br><span class="line-number">206</span><br><span class="line-number">207</span><br><span class="line-number">208</span><br><span class="line-number">209</span><br><span class="line-number">210</span><br><span class="line-number">211</span><br><span class="line-number">212</span><br><span class="line-number">213</span><br><span class="line-number">214</span><br><span class="line-number">215</span><br><span class="line-number">216</span><br><span class="line-number">217</span><br><span class="line-number">218</span><br><span class="line-number">219</span><br></div></div><h2 id="_12-单件模式"><a href="#_12-单件模式" class="header-anchor">#</a> 12.单件模式</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>就就这个位置就好，是吧？
啊，我我这样做呢，就是我刚才我感觉我就你到外面再看一下。
正好是吧。
ok. 
像我一会来的。
这样呢？
行，那我就直接录了啊。
好，那我们开始我们cdr 设计模式，singleton 单件模式。
这讲那。
呃，这个申购的模式呢，实际上是我们啊呃一个一个新的类别。
啊，大家看我们这里列就是对象性能模式。
呃，我我们为什么把这个题做对象性的模式呢？因为我们说面向对象，咱们二十四就经典的这二十三种设计模式啊。
我们说他主要是讲的是一个面向对象的手段。
在面向对象的很好的解决了抽象的问题。
其实到目前为止，大家前面学的绝大多数啊，其实所有的设计模式都是在谈一个关键词就是抽象，对吧？怎么样利用抽象的技术。
来实现一种松耦合的设计。啊，但是我们也要承认啊，就是抽象必不可免的会带来一定的代价。
比如说虚函数。
对，按照抽象里面就离不开渲染素和继承。
啊，继承本身的这个带来的这个内存啊，各方面的代价其实很少啊，几乎可以忽略。但是虚函数带来代价还是比较多的。
呃，在某些啊具有一些背景效应。什么叫背成效呀？就是。
本来这个事情做一次吧，哎呀，还做一万次啊，那这就被称教育，这时候的代价就会直线上升。
呃，对，通常情况啊一般情况下我说那样那样的这个成本呢，大多大家是可以忽略不计的。特别是在咱们四家语言里面啊，本身cr 这个语言的设计对于性能。
到了很好的考虑是吧，这已经实现了极高的性能的这样一个一个一个一个一个数。呃，就是呃。
优化的，但是呢。
面向对象有没有会潜在的有性能问题，在某我们只能说在某些非常特殊的场景下啊，他面向对象带来的成本的是。
需要谨慎处理的。那我们这里面下面讲两个模式啊，singleton 和fvt 就是来解决这个问题的啊，我们来看一下申购单件模式啊他。
他的整个这个场景是在软件系统中啊经常有一些特殊的类。
啊，必须保证他们在系统中只存在一个实例。
那么简单来说，只要他一次啊啊或者呃当然一般来讲我们说在站上你不太可能去呃，只是确保他一个对吧？但是我们一般堆上去吧，就这样一个对象。
呃，第一呢你要报成逻辑上的正确性。有些场景你这个对象只能有一个啊有多个就不对啊。第二种情况呢。
你没必要有多个，你有了多个的话，他的他会出现性的问题啊，那么也是希望大家只有一个。那这个时候怎么做？
我们知道一般的一个类，当你一个类做完之后呢，呃它默认就要构造气的吧，或者你给他提供一个构造器，那么你就可以创建很多的对象了。
啊，但是呢。
如何绕过常规的构造起来，提供一种机制来保证一个类只有一个实例。
那前面咱们如果学过那个呃一些工厂设计模式，或者有创建性的设计模式，大家知道利税模式绕过你是干什么的。为了避免你带来的解耦。
我们这里面绕过这个new 啊，或者绕过这个构造期，不是解决间耦合的问题，解决的是性能问题啊。
那当然有些朋友会说，哎，这个问题还不简单，我们只要只要告诉类的使用者，你一定要用一个呃只创建一个对象就可以了。
这就是我下面讲这个这个不是这个是类的设计者的责任啊，这不是使用者的责任。或者讲你不能把这个使用的这个。
这个这个这个责任全部推啊，就是这个这个保证只有一个责任全部推给使用者。
类的设计者，你首先要承担这个责任，就是使得一个类的使用者他做不到。
他不能够得到这个对象的，就这个类型的多个对象。
好，那我们来看怎么来实现。
这个。
嗯，这个代码实现里面啊有就有很很多很多的啊，这这就这种讲究了。我们来看一下这里边呢。
你打开我们这个这个申购存在嘛。
好，我们来看一下。
呃，首先呢最简单的几个处理。第一呢你要把他的。
构造函数拷贝构造函数设置成私有。
好，我们说大家知道为什么要胜任私有啊，有些朋友说我不写不就完了吗？
啊，不行的啊，学过释压碰撞，你不写这个构造器的话是吧？编译器会默认会帮你生成两个工友的，一个是缺省的拷贝构造函数。
一个是啊缺省的构造函数，对吧？
那么你要让外界不能使用它，唯一的做法就是设置一个private。这样关键词是他私有，私有就是外界不能用，我内部可以用。
然后呢我们再设计这个静态的变量，一个是静态的变量。第九行，一个是静态的这样一个成员函数。啊，惊叹变量呢我们在这儿给它初始化成一个knowledge。
这是一个指针对吧？因为我们确定他必须是一个堆对性啊，然后我们先来看第一种写法啊第一种写法。
看似很简单啊，就是我在这里面做这样一个事情。
af 做一个判断，af my instance 等于no。
啊，那刚开始第一次调用，大家想第一次调用肯定是闹，对吧？那这句话判断是触对吧？那么就进入到十七行这里，那就创建出来这样一个。
对象来。
然后呢，最后就返回，对吧？那么第二次调用呢？
如果有一个程序第二次调用的话，那当然这个就不是闹了，对吧？就不是，那就返回十九号，那是不是就永远也返回的，是这个。对，就是第一次创建了一个对象。
这很容易理解，对吧？这就保证了这个对象只有一个是吧？全局唯一啊达到我们的一个目的啊，但是新构成这么写的话，其实。
呃，他有一些其他的问题，什么问题就十四万，我这里。
这他在单线程环境底下。
他是ok 的对吧？
但是呢他是我说他是个线程非安全啊，就是在多线程环境下就不行。
但想想为什么多线程环境不行。比如我现在有两个thread，thread, a thread b 此外a 进的。
判断第一次调用啊，假设第一次啊是过了十六行，这个判断了，现在刚开始等一到的吧。
三十二a 还没有执行时期哈，那么现在室外的b 假如得到这个时间片开始执行，十六行了。
那他这是还这个时候是不是也知道啊，对吧？yc 那次也知道。
那么slide b 是不是也进到十六行这个判断里面了，就是要执行十七行。
那么这就意味着十六十七行贿被thread a 和b。
都会执行到。
对吧，就是在多线程情况下。
这个有可能啊。
出现这个对象被创建两个甚至三个多个的情况。
所以我们讲它是一个线程非安全的版本。
那当然这个就大家要考虑，那如果我想在实现一个多线程安全的一个版本，它应该怎么做呢？
这就是一个这也是一个非常著名的一个问题了。我们先来看看。
哎。
第一种。
考虑的做法啊，我们先来看一下，那就加速。
对吧？
加锁呢是一个呃常见的解解决方式了。呃，那比如说对刚才那个问题，我就在这儿放一个锁的。
所以这个所有的局部变量。
这个时候就变亮了，它会在什么？在这个函数结束的时候，就是大家知道你的局部变量在你结束的时候，你的生存周期要消失，你要调你的去勾器，对吧？
这个锁器钩器就会释放这个锁，会导致这个所得资源的释放。好，那就是实际上是对这个方法进行全局的一个加速。就是从二十九行一直到三十三号的一个枷锁。
枷锁之后呢，比如说咱们现在有两次right 的，此外a 进来了，那就首先在二十九行获取所对吧？
然后呢。
那就往下执行。在这个过程中，不管你在山上还是三十银行的任何一个地方，你另外一个线程进来，比如说thread b。
也调用这个方法，但是对不起。
a 已经获取这个锁了，而且他所还没有释放的，对吧，就没有执行完。三十三行。那么你thread b 是不是就进不来，对吧？那soyb 就等着。
一直要等出来的a 这个锁执行完三十三啊释放之后。
三d 才能。
这个这个获取这个数对吧，就进到二十九分。当然这个时候起来的b 进来之后，这个三十行一定已经不是闹了，对吧？肯定不是闹了。
所以这个判断就就跳过去，就直接执行三十三行就返回那个对象，那就肯定是对的，对吧？
那么说这个枷锁的版本，首先它是对的，它实现了我们singleton 设计模式的这样一个呃初中保证这个对象全局。唯一同时。
多写多线程又安全，对吧？我们说它是一个线程安全的版本。
但是这个里面的我这里有一句话，锁的代价过高。大家想这个锁代价在哪里啊？
假如啊。
现在。
这个词呃，这个对象已经创建出来了。
就是已经不是闹了这个指针mm instance，这个指针已经不是让。
那么。
现在假设有两线程同时访问。
近来二十九行。
是吧第一个线程绩到二十九行。
哎，比如说执行到三十行吧，假设第二个线程呃，假如这第二线程现在又抢到时间片开始执行的时候，那他能不能进二十九号，他不能进，对吧？因为对方。
是的，a 还在呢，还还。阿苏还没有释放锁。
但是大家想一想，这个时候有病，有没有必要加锁？
人民币啊其实没必要加锁，对吧？你想想为什么？
我们叫索其实这个这个里面有有一个模式，就是它是在读这个变量。
我不是在创建，就是这不是一个写操作，因为我已经不是闹了，对吧？但我不顺道的时候，我实际上这个时候两个两段代码都是在。
无这个变量获取这个概念。
读操作是不需要加锁的，对吧？就多个线程，比如说你有十个线程同时读一个变量，需不需要加锁，不需要。
对吧，没有没有什么安全的问题啊，只有有些县城是在写这个就改这个地方，就有读这个地方。这个时候你需要加速是吧？所以呢我们说这个时候呢，这个家具这个锁呢。
对，都是读操作的时候的县城呢是浪费的。
而所的是有代价的对吧？就是你你要等待嘛啊你其他的线程都要去等他。
当然这个问题说严重也不严重，如果说严重啊，也在某些情况下也可能很严重。
对吧，说不他不严重，因为你多个线程同时读的这个情况在某些场景可能没那么想象那么高是吧？但是如果你放在一个高并发。
所以高并发大家知道，比如说web 服务器对吧？外服务器这个典型的非常高频方并发的啊，同时十万人在线访问你一个的地方。那那这个十万十万人同时同假如他都要。
地点代码，那这个这个并发量就非常高了啊，所以我们说。
这里边如果在一些高并发的场景下，这个锁的代价还是可能会非常高的。阴。当然我们说实际上是这个时候没必要。
是吧你可以避免的。
所以呢很快的话，大家又发现发展出来一种新的一种实现方式。我们叫双检查所。
呃，这是非常著名的一个说法，叫double 啊check lock。什么叫double check lock 呢？大家看啊之前的一个版本是上去不管三七二十一先属。
现在不是。
现在是。
我上去先问一问这个变量是不是空值。
如果他空。
我才家属。
就是我才需要四十八号这个数如果不空。
我就压根就不需要加锁了，对吧？不空的话，大家知道直接返回就是了。
就五十三号直接返回，就是只有在空的情况下，我才需要加速。而且加完锁之后，大家看我这里面也要再判断一次。
是不是空？
如果这个时候还是空，我才创建。
唉，有些朋友会说，哎，钥匙怎么看这个呢？代码这这前后在所前判断来一直在锁后判断一次。有些人会迷惑这段代码会觉得。
主要这段行不行？
别人为我把那段删掉啊，假设不要那段。
大家想这段代码对不对？
你想一下啊。
肯定不对嘛，对吧？你想想他他他加这个锁就没有意义了啊，这四十八行锁就没有任何意义。你我们来看啊。
现在thread a 经过四十七行的判断进来了。
对吧，就假如刚开始是空啊，此外的a 进来了，然后在执行四十八行之前，为我强调的是之前啊。
在直营四十八之前，thread b. 
是不是进来的时候看这个my m instance 还是空啊，这衰的b 也进来了，对吧？就只只要能跑过四十七行的两个线程。
现在在四十七行之后在四十八号之前。
好，那确定五一你两段两个线程肯定不管你，即便家属，你也就是等一等，但但是你都会执行这段代码，对吧？
这是这段代码，五十行被两个线程执行了两次，那这个对象是不是有两个，所以这个地方也要加。
对吧？
就是四十九行，其实这一行的判断就是担心刚才我说的那个情况，就是在四十七号之后，四十八号之前。
两个线程抢劫了。
对吧，但是如果我们做了双检查的话。
就在术前检查还是术后检查？
啊，当然有些朋友说唉，那锁既然锁后检查锁钱就不要检查。
啊，所前不要检查，就会出现我们刚才说的这种，他虽然正确。
但是代价过高。
锁后如果不检查的时候，就根本就不正确，对吧？
所以所签署后都检查，大家看下所签检查一次避免了什么。
如果都是读取操作的时候，就是m instance 不是闹的时候都是读取操作，就没有这个这个代价过高的问题，是吧？那么所后检查的是。
避免什么进到四十七行之七之后呃，四十八号之前两个线程中同时进来的问。
啊，这样就double check，就是这就是double check 四十七号一次check 持久含x check。
好。
这是非常著名的，叫双检查锁的一种设计啊，然后。
呃，这个方式要说看起来很完美是吧？
啊，看起来很完美，就是觉得唉这个设计。
好像都正确。
但是我要告诉大家。
这个正确其实在计算机咱们编程行业相当一段时间迷惑了很多人，包括一些专家。
啊，而且这个问题也就是在大概两千年的时候左右啊，大概九九年到两千年的时候，才被一个专家，一个应该是加二领域的几个研究研究者啊。
发现。
而且很快就是在所有的语言里都发现这里面有问题，有漏洞，什么漏洞呢？
就是我这句话写的啊。
就是内存读写的这个。
有会出现reorder 的情况。
这个我需要细细解释一下啊，会导致双检查锁的失效。
啊。
嗯。
呃。
怎么样的一个一个一个一个一个一个失效问题呢？
我们来说这个啊还是来说这个m instance。
呃，就是说你这里边。
即便是加速啊，但是呢。
在我们这个。
两个县城里边啊。
他有可能会出现一种情况啊。
就是这个呃大家看这最好呃，当然这个reorder 啊在很多种情况下都会发生。我们先来解释，先来告诉大家什么叫reorder der。
啊。
就正常的情况下啊，大家看一个代码的话，它有一个指令序列，对吧？那么大家通常会认为这个指令序列会按照。
你所想象的那样的一个方式之间。
但是实际的在。
整个这个代码到了汇编层次到了指令层，到了cpu 的指令层的时候，我们知道线城市是在指令层次抢时间片的，对吧？
这这个这个指令和我们很多时候的假设有可能不一样。
啊，那我们来说一下，比如说五十行。
我是好像这里面呢这个做法啊，我们一般有这么几个假设无盛行背后啊，如果拆分的话，如果拆分成三个步骤的话。
他会怎么做的？第一个步骤是先什么？
先分配内存。
对吧，先分配一块内存。
这是第一步。step 一。
是的，要做什么？
要调用构造器对吧？say 构成的构造器。
这就这一般这个构造器就是对刚才分配的那块内存进行一些初始化是吧？第三步是什么？
把那个分呃，就是这些做完的这些东西呢，那个指针得到这个返回值，就是那个内存的地址给。
myst. 
是不是就这三步？
对吧？
大。
但是呢。
这三步是我们假想的顺序。
真正在cpu 层面。
啊，在指令级别这三步有可能被reorder。
re-order 之后呢有可能会变成什么呢？
就是先分配内存。
然后呢，把内存地址就给这个m instance。
直接就给i m e s。
然后最后再调用构造器。
要。
再再注意啊，我我刚才说的这个对吧？
就是这个默认的顺序啊，我再说一遍，常见的顺序是说。
啊，我们假定的顺序先分配内存，再这样过渡期，再把这个地址赋值给。
i miss 是吧，但是这个reorder 的之后呢，很有可能变成先分配内存，然后把这个内存地址给myst。
然后再。
再执行构造期。
耽误作为我这这里说的是有可能或者是很有可能。
啊，这是b 这是这是什么情况呢？就编译器处于他的优化的目的。
啊，他会有有时候会这么干，而且实际上很多研究啊就对这个汇编，对在不同的这个这个这个cpu 上做了实验，确实是会出现这种情况。
每一个语言都会有这种情况啊，java c 下啊，包括咱们自己家都会有用。
这。
这样一弄这个。
这个就有点儿乱套，对吧？
大家想一下这个这个怎么样会会乱套呢？
我们刚才说。
你那个必须执行完，你最后才给这个赋值，对吧？m a sentence 大家想想这个i m e 尺寸是是不是？
嗯。
呃，不是闹的，前提是什么？先执行完。如果按照我们的假设是先执行，先分配的内存，然后再执行构造器，然后才得到。
啊，他不是闹，对吧，才把它这个闹之改变就是复制一个真正的内存地址。
但是经过睿欧的之后，有可能变成一个什么情况呢？先。
先分配内存，然后直接就赋值了。注意m a 四的就不是闹了，对吧？
但是注意这个构造器还没调用的。
那么另外一个线程甲还进来啊，出来的b 进了。
从四十七行这里进来。
进来之后发现m 一四是不是不是闹，是吧？
不是，那那是不是就五十三啊，这边执行。
那就返回呗。
呃，这个这个对象就就得到了，是不是？
那得到这个对象，大家想这个对象是这个时候能不能用啊？
虽然在b 拿到这个对象。
此外，db 以以为他是可以用的，对吧？
但是实际上是不可以用的。为什么thread b 拿到这个mm 医生实际上只是分配了一个原生的内存。
并没有执行构造期。
就对象的状态是不对的。
对吧，就是这是发布双检查所欺骗了斯莱德b the thread b 拿到那个指针指向的那个对象只有内存地址，而没有执行构造体。
这就是双检查所有可能出现的问题啊。
呃，怎么解决这个问题呢？这个问题当然解决起来实际上相当复杂相当复杂。
而且早期大家发现这个问题啊。
几乎是没辙啊，那当然很快呢各家编译器厂商，这就是编译器要干的事儿，对吧？因为你别那个那个优化是编译器就reorder 那个优化是编译器感。
那第一呢java 和c crp 语言就很聪明啊，就加了一个关键字。
叫wallet tail。啊，大家大家如果到java 平台或者是crp 平台的话，你去看这个就是你需要如果实现双检查锁的话。
你需要加一个对那个加一个volte il 就这个实例变量，你加一个volatile 的声明。
这样的话，编译器在编译的时候就知道哦这个变量的。
整个这个赋值过程是不能reorder 的啊，是是编译器不能对他做这个优化的，需要按照常规的逻辑顺序走下来。
那就没有咱们刚才说的那个问题啊，就是一定是要些什么，先分配内存，再执行过渡期全都弄完之后再复制。
对吧？
呃，那c 佳佳呢c 加加首先用v c 加加大概在二零零五的版本里面，就vc 佳佳就觉得c 家标准太慢。
就给他加了一个wallet。tel 自家的一个关键字。
啊，但是这个这个显然不是跨平台的。
有事儿就我们说。
那只有微软的这个这个平台可以，对吧？其他家的这个平台就是不能实现。那cgi 又非常追求我们说跨平台的代码实现。
那只到世界幺幺版本之后啊。
才有这样的机制可以帮助我们。
实现所谓跨品牌的这样的一个方案。我们来看一下利用了。
这样一个at matic 啊这样一个标准库里边的一个这么一个范型的类型啊，怎么实现呢？首先呢声明一个。
啊，这样一个原子对象啊，这个原子对象呢大家看我在这里面去用load 的方式。i m e s 是这个啊no 的方式得到这个指针。
啊，这个指针就可以帮助啊我们实现这个就是屏蔽编译器的，reorder 的怎么屏蔽呢？使用。
六十九号啊就六十九衡，这里边呢？
有一个attic thread fancy。啊，这个fans 啊，我们可以理解成一个内存的屏障啊，就是一个内存reorder 的一个保护。
啊，那你那边传递这样一个啊符号，就可以确保获取一个内存的face。
啊，或许内存饭食之后呢，剩下的这段代码里边呢，就是这个tap tmp 这个变量就不会被他在他的副职里面。
就不会被瑞典了。简单来说一直到这里面的执行啊，当然这个lock 这个lock 语句还是需要放的，对吧？就是你你双检查锁，你锁还是要锁的。
啊，这个别只只是取变量的时候，都是用这种方式来取的。
天哪好，那在这里边其他判断都一样的，其实少。
这个就保证到七十市场不会出现什么reorder，就一定是先执行是吧？
嗯。
呃，这个内存分配啊，然后再执行构造器，再把这个变量给到啊，只给到这个team。
啊，然后在这里面啊，这这个也是一个那个相呼应的啊，这个注意这个是memory order release，一个是a appear，is great release. 
就我这里讲获取内存的fans，一个是试释放内存分。
好，这俩呢做完之后呢，这个store 再给它存回去啊，就是tap 等于在交给any 一次啊，就是呃就i m e 四呢，在娇娇回到这个。
太不理。
当你这个过程的返回，但不乏mm instance 都可以。
好，那就有这样的一种方式啊，在我们这个作为c 加e 版本之后啊，才实现了一个跨平台方案。
但具体有一些细节啊，这些标准库的这个啊船的这些参数啊啊大家可以去参考这个标准库里面的这个at matic。
它里面的一些实现的一些东西。
但总体来讲啊，我们来做一个总结。
来看一下。
呃，如果是单线程，你用这个就可以了啊，已经足够好了啊。
如果是多线程的，你用这个版本呢？
ok 不能说你是错的，但是你的效率不好是吧？代价过高。如果是高并发的话，它的这个是不合适的。
那双检查所不能用啊，说的也让他所示在所有的编译器里面啊，目前你如果不加我的跳或者这样一个设计的话，一定会出问题的。
啊，而且出问题的概率很高。这个在在很多呃研究啊，包括像scotman i e 啊或者一些idm 的家训机的一些实现的研究者写的论文里面。
对这个问题都有很深刻的一些统计性的研究啊，就是说这个问题是确实是在实际的过程中会出现的频率还是蛮高的。
那么。
嗯，在不同平台上有不同的实现。这样咱们c e r 幺幺版本之后啊，我们跨平台。
今天版本是这样子。
好，那我们这个问题就啊实现层面解释到这里。
好，我们简单的做一个总结这个模式啊，保证一个类仅有一个实例，并提供一个该实例的全局访问点。这个说起来很很很朴实，对吧？但我们知道具体时间有很多差异。
呃，结构呢这结构也很简单，对吧？就是一个有一个一个静态的陈函数，返回一个静态变量。
嗯。
呃，那么这个实例构造器呢，你我们说设计成私有，但在某些特殊情况啊，你为了此类派生，你可能也去也需要把它设置protected。
当然我们说这里面一定要注意，不要实现拷贝构造函数，包括一些克隆接口是吧？这个这个都可能导致他多个实力呃，最重要的或者这个。
singleton 里面最最最复杂的成功呢，本来是个简单的模式，对吧？本来是一个应该说是最简单的模式。
但是呢由于多线程环境的这样一个双检查锁里面的一些这这些内存聊了的一些问题。我们说实际上呢。
他实现起来啊，在一些细节的地方并不简单。所以最主要就是说大家需要注意啊，实现多线程环境下安全的一个做法。
双姐拿所目的正确实现必须注意内存的这个reorder。
好，那我们今天这个singleton 的模式就讲到这里。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br><span class="line-number">177</span><br><span class="line-number">178</span><br><span class="line-number">179</span><br><span class="line-number">180</span><br><span class="line-number">181</span><br><span class="line-number">182</span><br><span class="line-number">183</span><br><span class="line-number">184</span><br><span class="line-number">185</span><br><span class="line-number">186</span><br><span class="line-number">187</span><br><span class="line-number">188</span><br><span class="line-number">189</span><br><span class="line-number">190</span><br><span class="line-number">191</span><br><span class="line-number">192</span><br><span class="line-number">193</span><br><span class="line-number">194</span><br><span class="line-number">195</span><br><span class="line-number">196</span><br><span class="line-number">197</span><br><span class="line-number">198</span><br><span class="line-number">199</span><br><span class="line-number">200</span><br><span class="line-number">201</span><br><span class="line-number">202</span><br><span class="line-number">203</span><br><span class="line-number">204</span><br><span class="line-number">205</span><br><span class="line-number">206</span><br><span class="line-number">207</span><br><span class="line-number">208</span><br><span class="line-number">209</span><br><span class="line-number">210</span><br><span class="line-number">211</span><br><span class="line-number">212</span><br><span class="line-number">213</span><br><span class="line-number">214</span><br><span class="line-number">215</span><br><span class="line-number">216</span><br><span class="line-number">217</span><br><span class="line-number">218</span><br><span class="line-number">219</span><br><span class="line-number">220</span><br><span class="line-number">221</span><br><span class="line-number">222</span><br><span class="line-number">223</span><br><span class="line-number">224</span><br><span class="line-number">225</span><br><span class="line-number">226</span><br><span class="line-number">227</span><br><span class="line-number">228</span><br><span class="line-number">229</span><br><span class="line-number">230</span><br><span class="line-number">231</span><br><span class="line-number">232</span><br><span class="line-number">233</span><br><span class="line-number">234</span><br><span class="line-number">235</span><br><span class="line-number">236</span><br><span class="line-number">237</span><br><span class="line-number">238</span><br><span class="line-number">239</span><br><span class="line-number">240</span><br><span class="line-number">241</span><br><span class="line-number">242</span><br><span class="line-number">243</span><br><span class="line-number">244</span><br><span class="line-number">245</span><br><span class="line-number">246</span><br><span class="line-number">247</span><br><span class="line-number">248</span><br><span class="line-number">249</span><br><span class="line-number">250</span><br><span class="line-number">251</span><br><span class="line-number">252</span><br><span class="line-number">253</span><br><span class="line-number">254</span><br><span class="line-number">255</span><br><span class="line-number">256</span><br><span class="line-number">257</span><br><span class="line-number">258</span><br><span class="line-number">259</span><br><span class="line-number">260</span><br><span class="line-number">261</span><br><span class="line-number">262</span><br><span class="line-number">263</span><br><span class="line-number">264</span><br><span class="line-number">265</span><br><span class="line-number">266</span><br><span class="line-number">267</span><br><span class="line-number">268</span><br><span class="line-number">269</span><br><span class="line-number">270</span><br><span class="line-number">271</span><br><span class="line-number">272</span><br><span class="line-number">273</span><br><span class="line-number">274</span><br><span class="line-number">275</span><br><span class="line-number">276</span><br><span class="line-number">277</span><br><span class="line-number">278</span><br><span class="line-number">279</span><br><span class="line-number">280</span><br><span class="line-number">281</span><br><span class="line-number">282</span><br><span class="line-number">283</span><br><span class="line-number">284</span><br><span class="line-number">285</span><br><span class="line-number">286</span><br><span class="line-number">287</span><br><span class="line-number">288</span><br><span class="line-number">289</span><br><span class="line-number">290</span><br><span class="line-number">291</span><br><span class="line-number">292</span><br><span class="line-number">293</span><br><span class="line-number">294</span><br><span class="line-number">295</span><br><span class="line-number">296</span><br><span class="line-number">297</span><br><span class="line-number">298</span><br><span class="line-number">299</span><br><span class="line-number">300</span><br><span class="line-number">301</span><br><span class="line-number">302</span><br><span class="line-number">303</span><br><span class="line-number">304</span><br><span class="line-number">305</span><br><span class="line-number">306</span><br><span class="line-number">307</span><br><span class="line-number">308</span><br><span class="line-number">309</span><br><span class="line-number">310</span><br><span class="line-number">311</span><br><span class="line-number">312</span><br><span class="line-number">313</span><br><span class="line-number">314</span><br></div></div><h2 id="_13-享元模式"><a href="#_13-享元模式" class="header-anchor">#</a> 13.享元模式</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>好，那我们开始我们今天呃cr 设计模式f lev age。
啊，想源模式的健康讲座。
嗯，小燕模式跟我们前面讲的singleton 仍然属于一个我们讲性能模式啊，就是解决非抽象的问题啊，还是对象。
带来的这个性能成本的问题。
那我们说在软件系统中间，如果采用纯粹的对象方案。
有的情况下，如果大量的细腻度的对象。
啊，会会很快充斥在系统。
呃。
从而会带来很高的一个运行代价。
就我们说面向对象呢general 来看呢。
你可能不用太担心他信了吧。相对我们说传统的过程语言啊或者其他的。
呃，但是呢在某些场景底下啊，一旦这个量就是我们说的有倍乘效应啊，就是你你几十个几百个显现不出来。
但如果是几万个、几十万个这种对象就会带来问题。
呃，我们知道嗯。
纯粹的面向对象方案啊，所以纯粹就是一切皆对象，是吧？在八十年代中后期呢是有这样一种思潮。
呃，特别是从最早这个small talk 开始啊，有一种思潮就是一切皆对象，对吧？但是。
后来大家时间下来发现一切皆对象并不现实啊，比如说一个一啊一个double 这样的类型，实际上没必没必要用对象。
但是呢在业务场景过程中也是有一些很小的东西啊，你看起来很就是我们讲的细腻度的一些啊很小的。
但你你可能会在设计上也考虑到把它设计成对象。但是由于你用的特别亮，他特别大，这个时候呢对象呢可能会带来一些开销。
啊。
那这个时候怎么办呢？难道是说不用了吗？啊，我们所以这个时候常见的优化方法其实就是早一些什么是不是可以。
共享方方式啊。
共享技术呢是一个。
嗯，咱们在面向对象里面啊。
这个这个经常来解决性能问题的一个一个手段啊。这也是fly away 这个整个这个设计模式的一个核心的思想啊。
呃。
那比如说字符串这个事情。
啊，字符串大家知道在我们的系统中沿用了量是非常之大的。
啊，常见的呃这个这个这个呃就是呃软件系统啊，你不管是java 或者c upp 或视觉家这样的一个软件，你写的系统里面。
不串产生在你这个占用的这个。
嗯，内存比重都是比较大的啊，那么这个时候呢我们说常见的系统，包括咱们sql 啊库里面对字符串其实都用了一定的共享技术。
啊。
当当然有些语言呢，比如说像java c hr 不叫语言，他会在一些编译器层面啊，就是在一些或者他的g i t 编译器层面。
啊，他甚至都不是类库层面啊，它用了一些共享技术。
这些共享技术呢，你严格意义上来讲，看起来可能和我们今天讲的flat white 的这个实现的方式可能不一样。但他的思想都是一样。
就是用共享技术来。
有效的支持大量细粒度的对象。
这个量啊，那呃除了字符串呢，比如说像县城是吧，线程池也是这样一个一个问题啊，那现在也是一个开销很大的。
那场参加我们就会用线程池来实现一些共享的技术。
当然这个这这个句话里面啊，这个大量量到什么传销大，对吧？这个是需要评估的啊，是需要你针对你的系统的实际的channel。
然后去评估，然后真正的去测量一个一个对象在量多大的情况下，会带来内存层面的负担。
啊，或者资源方面的负担。
呃，当然我们这里主要讲的内存，但是实际上除了内存之外啊，其他的资源也是经常会有这样的情况。
好，我们来看一下这个g o f 对这个flav 的一个定义啊，就是它的一个啊有面向对象的方式的一种描述方法。
实际上大家可以看一下这个类图。
那么这里边是一个factory 啊，一个叫蒋媛的工厂。这个工厂呢本来你创建对象的话，一个一个去new 这个对象，对吧？现在我们说。
你你有的时候你有可能是有一些本来可以共享，你却没有共享。那如果用这个想圆的工厂的话，就是get flight，这里边传容易。
所以这个方法这个方法有一个参数叫k 这个k 在里边去做一个判断啊。那么如果你这个这这个数据结构里面的这个k 如果存在的话，也就是你这个对象已经创建过的话。
就不要再创建新的对象，直接返回之前那个对象就可以了啊。但是呢如果你这个对象之前不存在，就没有创建过。
那么就先创建一个。
然后创建完之后呢，再给它加到你这个对象池里。
然后再把它返回啊，基本的思想就是这样子。至于下边啊右下角这个地方啊，大家其实是可以忽略啊，就是有些痣有些对象是知识想圆的，有些就是对象是不知是小人。
啊，就是不支持共享。
好，我们我们也呃根据这个呢我们可以给大家一个一个适应性的代码例子。啊，当然在具体实现过程中啊，这个也是差别非常大的。
我们举一个例子啊，就比如说咱们需要设计一个呃字处理的系统啊，那这里面有很多的假假设啊，你把字体兑现。
实现成了一种对象啊，这就是我们说纯粹的面向对象的这种观点，就一切皆对象。但是我们也得承认，有的情况下，甚至有些方案。
直接抛弃什么面向对象啊，这就由于这个原因就不用对象啊。当我们这里面假设我们一切皆对象，还是用了对象。
就用一个font 类来描述这个字体。
那么知道这个字体对象呢，其实是他量很大，他有可能对吧？你一个系统里边一严格意义上来讲啊，你每一个字符都有一个字体。
对吧你这个字体都是，但是实际上算下来，大家想一想。
你比如说你你你是啊这个十篇文章，对吧？
哎，就实业文章啊，企业文章底下你你去看他的这个真正用的字体的话，一般也不过呃四五种，七八种了不起了，对吧？不可能是说。
每一个字字符的字体对象都是不同的。
那所以其实是说绝大多数字符的字体对象是是相同的。
如果你不加区分的来去创为每一个字符创建一个自己对象，那你这个系统。
啊，很难承受了，对吧？就是你的你比如说你有。
几十万个字符，那你就一定有几十万个磁体对象，这个是很很很大的一个数据啊。
那这个时候怎么办？
就是你需要。
用我们的这种响应的方式来设计啊，比如说那字体呢一般来讲你是能够找到或者能够确定他一个kid。
啊，比如说这个字体的名字就是他的k 啊是用一个字符串来代表。
好，你可以使用这个k 呢，可以load 到自己的相关的资源，对吧？一些图源资源啊等等。
啊，总之就是说在构造器里，你可以用这个k 构建你这个对象。
这么来看，呃，我们真正的呃推荐的创建方式呢就是这样的一种创建方式。
打开来我们这儿测定另一个字体的工厂。那就是我们刚才那个fly v 的一个factory 工厂。然后我们用了一个map 这样一个数据结构。
啊，这个map 呢我们知道就是来维持啊这样的一个所谓的字体对象的池啊自体值。
found the pool. 啊，这个方式呢在我们这里边呢。
打开了我们去第二次这个这个方子的时候呢，我们传递一个k 这样的一个一个呃一个字符串。
然后呢我们在这里面首先去查找。
对吧这个方铺啊，它有一个废人的方法去查找这个key。
如果这个k 找到了啊，首先找到，那么判断就是这个。
迭代器啊不等于这个结尾是吧？ok 那我们就可以返回他，那么就直接返回，就说明之前创建过了。
如果没有找到，就说明之前这种对象没有创建过没有创建过。我们首先来创建一下。
啊，就是优放的传说也是这个k。
那我们把这个。
嗯，同时呢找到之后呢，我们要呃就是创建之后我们要把它存储到我们的或者叫添加到咱们之前的那个对象池里边。
对吧，再就是三十二行这个做法。
添加到对象池之后呢，我们返回，再再把这个对象返回。
这样的话就是大家可以看到你你同一种。
k 永远在系统里面，只有什么一个字体对象相对应是吧，就是只创建了一个字体对象，你不会有很多个。
啊，那么当然你的kh 有限的对吧？我们说你你可能有十万个字符，其实你只有比如说十种字体对象，那么你就只有十个k 在那里。
那这样的话，你的系统里面啊只是维持了十个字体对象。
也就是说维持在这个map 里。
然后每次get 的时候就取他就可以了。
其大家看这个实现起来啊，各种各样啊，甚至你数据结构你都可以用啊，不不一样的数据结构是吧？但总总体核心的思想是什么？
就是用共享的方式，大家看这个地方就是一种共享的方式。那我也有就返回，没有把它添加进去。然后反呃实际上这是常见的一个对象池的一个一个设计方式。
呃，发威的实现起来呃，不难啊，当然也也五花八门啊，其实在现实的过程中，你实现的数据结构也有不一样，包括接口。
包括这个ky 的表达是不是单独一个k 就可以完成的啊，是不是这个这个类型啊，包括这个这个呃这个船这个构造器，通过这个k 啊来构建这个对象的过程。
其实都是有一些具体实现细节上面的很多差异的啊，但是。
我们说总体来讲这样的一个设计思想啊，就是咱们想圆的一个啊啊宗旨。
因为我们说通过一种共享的方案是吧，来支持大量的细粒度的这样一个对象。
呃，我也说了，其实啊在代码层面，咱们刚才是一个事宜。但是在有些语言里面，这样java 包括swift 啊。
包括cgi 家，呃，包括这个c shup 啊这些语言里面，其实他都会在编译器层面。
啊，在这个编译过程里边会实现了一种啊这种fly 唯一一种设计啊，这样的话就你就不用不用再代码去做了。但是它内部的实现原理呢。
其实跟我们这个差不多，也是在一个所谓比如说字符串池里面去查找，查到了返回没有查到呃，就。
创建是吧，这样的话以系统中间的字符串的量就没有那么大。
啊，呃线程池也也是类似的啊。
好，那个。
呃，这个小袁呢实现起来啊，在在平台上表现层面五花八门。但是总体思想大家了解他解决的是。
还是性的问题啊，就是我们说面向这样解决抽象性问题。但是华为才能是比较独特的和和我们新构成这两个模式啊，呃咱们咱们整个设计模式呢只有。
这两个模式是解决的，不是抽象性的问题，他解决的是这个性能问题啊，代表。
嗯。
fleet 的解决思路就是采用共享的做法。
啊，共享的做这个。
做法来降低什么个数？
当然这个前提是你有共享的空间，对吧？
呃，也就是你系统里面很多对象是一样的，它的状态都是一样的。呃，我也需要在提醒一下啊，这里边其实常常它有一个条件就是。
咱们这里对象创建出来之后啊，放到创建之后，他就不能更改了。
你不能更改这个对象的状态，所以往往这种对象呢出来之后都是只读的。
对吧，这也是大家大家想一想这个这呃像在c up 普java 里面的字符串都是制毒的啊，当然cg 标准库里面支付账不是只读的，但实际上背后他用了我们之前讲的一个proxy 设计模式。
来解决他的就是靠背on right 的问题啊，但总体而来讲啊。
大家要了解这样的一些对象，你出去最好是治堵的啊，呃否则的话你这个共享就就不成立了，对吧？你共享给别人之后，别人把那个改了，那你。
另外的地方使用这个对象也被更改，所以他有这样一个背后的一个一个隐隐含的要求。
嗯，就是我们这里讲的这句话。
啊，就是在具体实现的时候呢，要注意这个对象状态的处理。
这个状态就是我们说一般来讲啊，尽可能的实现之毒的方式。
呃，当然最后一个我们也要说一下，对象数量太大会导致对象开销大。那我们一定要说要有一个具体的评估，对吧？什么样的塑料才算大？
他到底占用你内存多少啊？我们可以来做一个简单的啊说明啊。
比如说在咱们cg 里面。
这样一个对象，它到底占有多大？
首先我们说一个对象呢。
你的字段啊，我简单说一下，其实就是set off 啊，对吧？你拿到你哪个对象，你首先用一下cgi 的赛道。
呃，但但是我们说你当然你不见得你你你首先有一个经验，你要去评估对吧？你这个对象有多大？
首先所有的字段的int double 啊，这些自产多长把它加起来。
除了这些加起来之外，还有一些其他的因素。比如说你这个自己也有对其的因素。
啊，是留在咱们三十二平台上，四个字节要对其啊呃对其的因素算上可能会变成让你变得更长。再加上还有什么因素啊？
还有你这个虚函数对吧？如果你你这个对象有虚函数的话啊，那么你选手表指针啊会占用多少？
哎，四个by 是吧。
呃，三十二位的机器上四个by 啊，六十四位就就八个半条了啊，就是这是一个指针的大小了啊，当然当然这个根据讯函数多少没关系啊啊你你你有十个渲染出，它也就是一个渲染疏表指针。
啊，在对象模型里面实际上是有这个说法的啊，那么这个通过加起来之后，形成以一个对象的size。然后你就看你这个对象读。
啊，多少个啊，比如说你这个对象。
假如你有十个hint 字段。
哎，假设啊适应症字段，那你算算一下是多少三十二位机器啊，一个一四个b t 啊，十个字段乘以四十个b 的那四十个白态。如果你有一千个对象，你有多大？
一千个对象。
我们给你算一下，对吧？一千来咱咱们就要用幺零二四吧。比如说这个诚意，刚才我们说呃四十个b 啊。
也就是什么。
四十k 是吧啊。
四十k k b 啊。
四十kb 其实。
不算不算大是吧，也不并不算一个一个一个特别可观的一个数据。
但是如果你在成呢，比如说。
假如你啊再乘以一个一百啊，这个大概就有啊多少。
四四千k b 了对吧？大约是什么？大约多少四兆了是吧，四兆已经已经比较可观了。当然当然嗯。
你大概估计一下这个是多少啊。
这多少个对象就一百个千啊啊十万个对象就是说你对象如果有十万个的话，你大概有十个左右的印象字段的话，你这光这。
一个对象啊，就光这一类对象在你系统中间占用的大概是五兆左右啊，那这个是相当可观了，相当大的一个数字的。
吧。
所以我们粗略的估计啊，就是说你对象上十万。
啊，在这个五兆左右的水平，对吧？如果你是十呃一万呢？
一万个对象，你大概是什么？是零点五兆啊这样一个水平，对吧？就是这个你要自己评估啊，跟你相对你系统的整体的内存水平，这个内存是不是占用比较高。
大。
你也可以看看你常用的进程，对吧？就常见的例子，你看看它内存大概几张五六兆，七八兆多一点，八十呃八九十兆对吧？上一百兆的进程是很少的。
啊，常见的就我们如果说客户端的系统，服务端系统，当然这个进程就就变得更大了啊。
呃，这些都需要仔细的做评估啊，根据一些经验数值，包括你系统的容量，你设计的这个这个可用性对吧？内存的整个整个可用性来讲啊。
这都需要评估啊，不能不能一起啊，不能是说哎我觉得他打实际上你算下来，比如说你只有。
三四百个对象是吧，你算下来其实可能没那么多，对吧？就是呈下来没那么多。而且fvt 本身啊你去实现反美的本身，他他这个数据结构也是需要。
需要额外的开销量。
这些数据结构内部也有偶尔看一下，所以你要去评估，你不能说几十个对象，你就去用fleet，这个就并不科学啊。
好，这所以flite 实现起来啊并不复杂，对吧？但最主要就是你要去根据你的应用情况去做评估，然后以相应的啊。
品牌的这个这个数据结构啊，或者某种设计的方式来实现的。
呃，我们这里只是给大家提供了一种参考的方案而已。
好，那我们今天这个flight 呢就讲到这里。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br></div></div><h2 id="_14-门面模式"><a href="#_14-门面模式" class="header-anchor">#</a> 14.门面模式</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>嗯嗯嗯好，那我们开始我们c加设计模式发射的门面模式的这个讲座。
呃首先注意一下这个词啊，大家看这个词是这个这个其实不是咱们英文里面c，这是一个法文啊。
fast。
那么中文翻译成门面或者界面，我们首先来看一下这个模式呢我们把它归到接口隔离模式里面啊那在这接口隔离模式里面，除了发射的还有什么proxy、adviser啊这些模式，为什么我们说把它归到接口隔离呢？
我们来看一下啊，就在组件的构建过程中，某些接口之间直接的依赖常常会带来一些问题，甚至根本无法实现。
我们说这个时候采用一层间接层，大家看间接。
嗯间接呢是一个非常重要的软件里面的一个一个思想啊，它几乎会充斥着咱们在软件的生涯里面的各种涉及问题。
呃最简单来说，比如说c加加里面的这个指针，其实就是对象的一个见解，对吧？
那么嗯如果更大从更宏大的一些层面来看呢，软件的诞生本身就是一种间接思想啊大家知道其实我们知道在最早有计算机的时候呢，其实是没有软件的人和计算机的硬件直接打交道，对吧？
那么后来呢有了软件啊，其实就是在人和硬件之间实现了一种。
间接层，就软件是硬件的一种间接啊，人直接去操控软件啊然后来控制硬件。
那么后来呢我们发现在软件和硬件之间呢呃其实又有一些东西可以提出来，就是操作系统，对吧？
大家可以想象一下，就是操作系统里面，比如说把一些进程管理啊、内存管理啊、资源管理啊等等啊抽象出来，变成一个稳定的东西。
那么实现了什么软件和硬件之间的一层间接层啊，就操作系统变成他们之间的见解。
呃当然这个间接大家想想想象一下，这个间接的提出实际上就是稳定和变化的剥离，对吗？
呃软件里面剥离出来那些稳定的部分变成操作系统。
因为我们说相对来讲操作系统要稳定，应用软件会更变化频度高。
高一些，对吧？
那再后来呢，大家知道在软件和操作系统之间呢，大家又发现有一些东西可以稳定下来，比如说中间件，比如说虚拟机是吧？
像像java虚拟机啊，或者是微软的dota的cr这样虚拟机啊又是一层级间接层。
所以我们说间接这种设计思想啊在我们这个呃这个软件行业是是非常非常这个频繁的啊。
嗯那么咱们设计模式里边其实以已经遇到很多间接思想了，是吧？
举例来说，咱们最经典的依赖倒置啊原则啊，它其实本来是a依赖b的，对吧？
那我后来做了一层间接之后，就是a去依赖i、b这个接口，然后b来去依赖b的接口，它也是一种间接思想。
呃所以。
我我记得有一位软件界大师啊就讲软件设计的思想，核心的关键词啊其实就是这个间接english。
那么当你没有没有好的办法的时候，当你没有好的解决方案去去面对你的问题的时候，你想一想用一些间接的思路来去解决它，往往就有一些方法出来。
啊那我们这里讲的这几个设计模式呢都是跟咱们这个间接思想有着极其密切的关系。
当然我们也强调一如所往，就是说并不是说只有这四个模式才有接口隔离这样一个间接思想，其他模式就没有，而是说这四个模式在这个层面体现的特别特别的典型、特别的明显。
其他有些模式呢也有啊也有啊。
好，那我们来看一下这个发。
现在模式在解决这个问题的时候是怎么样？
呃一个一个一个角度啊。
首先呢呃大家看这个图里面的左边的这个a方案，a方案里边呢我们说它是有一个问题，就在我们设计一个子系统的时候呢，如果你这个子系统内部啊，我们这个方框这个方框啊框起来这个内部和方框的外部，我们叫客户系统产生了一个很多的减偶和关系。
我举一个例子，比如说咱们常常设计很多系统里面要有数据访问系统，对吧？
那数据访问呢这个里要牵扯到很多层面的对象，举例来说，连接对象、命令对象啊、数据表啊、一些参数对象等等，mv就非常多了。
那么如果你不加约束啊，不考虑。
任何设计的话，你可能很容易写出一种方案，就是你的对象你的这些呃外部的对象会和这些数据命令对象、链接对象进行直接的偶合，但这个直接的偶合呢是很不好的，你又就你又会看到系统非常的散漫，对吧？
那么好的方案是什么啊？
呃我们说你提出一个间接层啊就是这个fast，我把我用红色来把它框起来，发色的提出，其实就是在这个层面加一层接口，这层接口隔离所有的数据连接、对象、命令、对象参数、对象表结构等等啊隔离起来。
然后呢外界客户啊外界就是这个客户客户类呢只和fast这层接口来打交道。
那么。
内部本身呢这个互相之间偶合啊和发散的进进行进行关联偶合。
但是内部三呃这个系统和外部啊就外部你是看不到什么数据连接对象啊、命令对象、参数对象等等这些啊，这个其实就是发射的一个设计的一个总体的一这样一个一个方法。
好，我们来看一下这个设计的。
当然这个场景其实我们刚才已经通过那个图来解读了，对吧？
就上述a方案的问题，就是组建的客户和这个组件中间的这个各复杂级系统有了过多的耦合。
啊那么随着这个系统的演化呢，子系统的演化，比如说什么演化就是一种变化，对吧？
呃呃举例来说，我们以前这个。
呃数据库啊系统子系统用的是什么数据房层用的是针对比如说mysql的数据库的一种访问方案。
啊然后呢过一段时间呢我们可能会切换到alt上啊，同时呢我们可能里边的连接模型里边的数据加载模加载方式都可能会有一些变化啊这个这个时候呢如果我们没有用发射的模式，那么a方案就带来非常激烈的这种震动，对吧？
但是如果我们用了发散模式的话，我们说不管你内部怎么变，我的外部看到的接口仍然是一致的，这就是发射的这样一个模式。
解决问题的角度。
呃实际上提出一个一致的模型，就简化了外部客户程序和系统间的一个交互。
好，如果我们来看一下j，y。
f对这个发散模式的一个定义啊，就为子系统中的一组接口提供一个一致的界面。
注意这个一致啊是一个我把它框起来就是稳定，所以一致就是稳定。
那么fast模式定义了一个高层接口，这个接口使得这一子系统更加容易使用，什么叫容易使用？
就是复用。
你有一致性，你稳定了，那我就可以一直使用你，对吧？
我就不被变化。
对外部客户程序来讲啊，但是你内部的变化啊怎么样来都无所谓，这实际上是就是用一种隔离的方式，对吧？
把变化和稳定隔离起来，拆解开来。
呃当然发射的模式具体在实现的过程中啊，它其实呢没有一个特特定的一种代码结构啊。
呃甚至可以说你呃看起来代码结构相差度非常大的啊，呃千差万别的代码结构它可能都表达的是发散的模式。
那么所以我们在这里呢这次课呢我们不给大家去展示某一种说哎这个什么样的代码结构叫发射的模式。
啊实际上发射的模式呢它体现的是一种设计原则和一种思想的表达，也就是在子系统内部和外部的一种结偶的方式。
那么在现实的开发过程中啊，你在不同的场景里边啊这个发射的表达方式差差异度非常大啊。
但是大家一定要理解它的display在哪里。
所谓的display就是说他要把子系统的这样一个变化给他圈住，就像我们刚才举例数据访问层啊就是。
典型的一个发色的设计模式的一个应用，他要把数据对象所有有关数据对象的东西全部圈在这个这个框的内部。
呃那我这里也来画一下啊，就是咱们首先来看，比如说这个部分，红色的部分是稳定的部分啊，没就是跟数据库具体信息无关的部分啊，比如说我返回的是某些数据对象，某些数据的更改等等啊。
那么我们再来看这个里边呢里边这些对象啊，这一个一个对象可能是比如说数据连接对象、数据命令、对象、数据参数、对象啊、数据结表、结构啊等等啊，那这些是经常变化的，对吧？
这些有可能比如说就我们说的啊，你你今天是mysql，过一段时间是偶尔。
不夸张的啊，那包括你的数据的表结构，因为你的连接模型不一样，你的表结构啊也表达的不一样啊但是这些东西都不影响什么红色部分的稳定性，这样就实现了什么红色就是对蓝色的一个隔离，就是用一个稳定的接口隔离变化体。
这是咱们呃发射的模式啊在系统级的这个表现。
好，呃我们做一个对这个模式的一个一个一个总结啊，我们说从客户程序的角度来看啊，发射的模式简化了整个组件系统的接口啊对组建内部与外部客户程序来说呢，达到了一种解呕的效果。
所以这个择偶这些也是一个关键。
内部子系统的任何变化不会影响到发射的接口的变化。
然后发射的设计模式更注重成什么架构的层次来看待整个系统，而不是单个类的层。
所以fast永远是处理多个类形成的一种系统级的这样的一个啊啊设计啊，而不是说单个类的层次啊发赛的很多时候更多的是一种架构设计模式。
嗯其实这个模式呢也不是嗯也也不是说这个呃很多是模式的设计思想都都不是来源于软件本身。
啊如果大家看发色的，比如说我眼前的这个电脑，是吧，电脑的设计其实咱们也可以它的硬件设计也可以典型的理解成是一个发射的模式的应用啊。
比如说嗯我们说一个店呢都有所谓的外部接口，显示器是它一个外部接口啊，对吧？
它的键盘是它外部接口，包括今天他的鼠标，比如说他通过蓝牙信号啊发产产生的这个鼠标的连接啊也是一个外部接口，还有他一些电源接口啊啊、usb接口啊等等，这些都是它的外部接口，对吧？
接外部接口我们知道实际上是和用户客户打交道的，你是不变的，对吧？
或者是倾向于稳定的，但是你的内部接口啊就是你的内部的cpu、你内部的内存条儿啊，你内部的硬盘啊，这个包括你的主板等等这些东西你是经常在更产品的更新换代过程中经常在变的，但是你你你面向用户的这套外部的接口是不变的啊那么如果从这个角度。
来讲，你看这个这个电脑的设计，包括我们说手机的设计啊，其实它都是遵从了一个general的一个设计原则。
这个设计原则其实都是我们都可以看作是一种发色的啊。
对，所以发色这个模式呢其实是一种是一种设计素养，这种设计修养啊，你你在你考虑一个问题的时候，你需要有这种边界的划分，需要有所谓对外的层次和对内的层啊就是对外的层次你要保持它的稳定性啊，呃这样的话用户才有一种稳定可靠的感觉，对吧？
但对内的层次呢，你是要快速迭代的，你的产品的future，功能的强大、性能的提升啊等等这些方面啊所以我们的软件行业的整个很多咱们讲的是很多设计模式，其实的思想你都可以从传统。
行业里边找到智慧啊就像我们最早讲的面向接口的这个设计思想，其实也是从传统行业会找到很多智慧啊。
呃软件行软件虽然是一个我们说是一个虚拟的世界对吧，是一个虚拟的载体，但是呢它的设计它的很多的设计的这种原则思想呃来自咱们传统行业的很多智慧啊你都可以发现。
嗯最后一点，我们说发色的设计模式啊并非一个集装箱啊，你可以任意地往进放任何对象，实际上它的核心就是说这个内部呢必须是相互偶合关系比较大的，对吧？
你比如说就拿数据访问层来讲，你用了fast之后，你当然就有一个约束，就是你不能不能把一个比如说呃用户界面的一个组件，比如说一个一个一个button塞进来，或者是一个html五的一个一个什么呢？
给原件塞进来，你都不可以这样做，对吧？
为什么？
你既然界定了这个这个发色的这层，它表达的是数据访问层，那么他就应该只应该做数据访问的工作，那么里边的对象呢都应该是什么数据访问相关的偶合关系比较大的那些组件，而不应该再来其他组件。
啊这就是所谓我们的原则，叫什么松偶和高内具啊，就发射在它的内部是高内聚的，对外是双偶合的。
好，那我们今天这个发射的模式就讲到这里。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br></div></div><h2 id="_15-代理模式"><a href="#_15-代理模式" class="header-anchor">#</a> 15.代理模式</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>嗯。
好，大家好，那我们开始我们cr 设计模式啊，代理模式。
foxy 啊，所以这个讲座。
那代理模式呢也一样，是属于咱们接口隔离模式，就是增加一层间接层来解决问题的这样一个一个模式。
呃，我们来看一下代理模式的这个。
问题的场景啊，他是在面向对象系统中，由于对象由于某种原因啊，这个原因呢啊各种各样了。比如说对象创建的开销可能很大。
啊，或者呢某些操作呢需要一些安全的控制。
啊，或者需要一些进程外的访问啊，所以说你这个对象对吧，是在这个机器上。然后呢你要创建一些其他对象在。
通过一些分布式的方式，对吧？在另外的进程，甚至另外的机器上去访问它。而这个时候呢。
我们说直接的访问会给使用者或者系统带来麻烦，甚至完全做不到。
对吧，就像我们说分析一个分布式的我的系统啊，你要去访问那个机器上的对象，那是做不到的啊，这个时候怎么办？
啊，我们说如何在不失去透明操作。所谓透明操作啊，这是一致一致性就是说哎我。
我假想如果我本来访问你这个对象的方式是比如说new 一个对象，然后调用你的接口，对吧？那我现在呃能不能还用类似这种方式？
来一句访问你。但是至于背后的那些麻烦事儿，比如说你对象的开销很大，你需要做一些优化，你或者需要做一些安全的控制，或者需要做一些分布式的方案。
我都不知道啊，就对我实现隔离啊。
就是既透明操作，同时又能实现那些额外的功能啊，这增加一层间接层是我们这个proxy 的一个解决方法。
我们来看一下这个模式的定义啊，为其他对象提供一种代理。
以控制。
啊，这个控制啊其实就是咱们这里面的隔离。
这个隔离的方式就使用接口啊控制这个对象的访问。我们来看一下这个模式的结构啊。
这个模式呃结构其实看起来很简单啊，但是呢他真正的实际使用过程中啊，它可能会变得非常复杂。
常。
比如说咱们现在说有一个呃主体对象。
啊，呃这个这个主体真正的对象啊在在这里。
啊，我把它用，其实这个部分呢我还是用蓝色的。呃，我我先来画他们的接口啊，他们的接口呢是这个。
这个是红色的。
啊。
然后呢，真主体就是实际的对象呢是哪个，我们来看一下。
嗯。
我调一个颜色。
实际的对象呢是这个。
就是说本来我要访问的时候，我应该是一种啊client 应该是直接去。
创建一个什么，就是啊声明车sub subject 的一个接口是吧？然后我真正实际创建的是一个real subject 这样一个对象。
但是呢由于某种特殊的原因，就像我们刚才说哎，直接的对象由于可能需要访问控制，安全上面可能需要做一些。
呃，优化性能优化的原因可能需要甚至说是分布式的电影，我们做不到，对吧？那这个时候呢。
我就应该什么应该client 应该直接去访问这个proxy。
啊。
这个proxy。
然后呢，proxy 和这个real subject 的之间呢。
那当然这个这个摄影模式这里画这个啊其实不太嗯真正实际上不是这么干的，对吧？因为这个这么干也太简单了。
啊，他真正要做的事情背后很复杂，比如说就是这个省略号这个点点点这样描述的。你如果是性能的方式，如果是安全控制的方式。
或者是一些分布式的分布式，你就压根就没法这样做，对吧？分布式你需要什么？按照一些消息协议来传递一些啊i p 啊。
个数据包啊，然后这些数据包过去之后呢再解包，然后那边呢再做一些事情啊。呃所以这个呢是一个。
嗯，啊只是一个很很很overview al 的一个一个一个设计的概要图。但真正在咱们的一个。
开发系统里边啊，这个做起来可能会很复杂啊，我们来举一个例子啊，就是用一个。当然这个例子也是非常嗯非常。
简单啊一个一个适应性的一个例子。我们来看一下，比如说我们在这里创建一个。
创建一个proceed 的一个文件夹。
好，然后呢我们在这边呢。
假如我们拿拿拿两个拿一个文件过来啊，随便来一个，你要过来。
啊，比如说这是time。
啊。
在按常规的做法呢，我们这个client 的访问呢应该是一个什么样的一个方式呢？
嗯。
我把这些都先去掉。
比如说我们这里class。
我有一个嗯啊我们就按照咱们这个slide 里边的这个。
比如说这个是subject 的一个接口啊，那我一般作为接口，我还是倾向于写成i subject。
带一个这个啊，然后当然你里边可能有各种各样的虚函数啊，我就用一个来表示y 的，比如说process 这样的函数啊。
那我们说啊你有一个a view。
i view subject. 
去继承或者讲实现了这样subject 啊。
然后呢，当然你去在这里边具体。
具体去实现他了，可能会做一些各种各样的事情。
嗯。
啊，我这里面假设你做了一些事情，对吧？然后我们再来一个说client，比如说在这个。
thanks. 
app 里边。
啊，我们可能有一些函数，比如说这个。
嗯，我的。
嗯。
多啊。
呃，呃某某某一个任务我都踏实。
啊，那假如这里边呢可能那一种做法就是说我在这个地方呢，我声明一个。
i subject. 
啊。
然后呢，当然我在我的构造函数放大一点。
然后拿着我这个subject 可能就要去调用这些。
process 之类的方法啊，按那个做做各种各样的事情，但可能不是这么一个方法啊，可能有很多很多方法的啊。
然后呢，在这个地方呢。
啊，我需要再填一个什么构造构造器，对吧？比如说嗯client 的a p p，然后。
啊，这个构造器里边呢，我可能就是。
通过比如说通过某种工厂的模式啊，或者是一些其他方式，总之就是绕来绕去生成了一个real subject。
假设啊。
啊，通过某种方式，但是我们说这这种方式我们说不合适，原因是什么？就是这个可能是由于性能的原因，可能是由于安全控制的原因。
可能是甚至分布式的原因，你压根就拿不到这个real subject，对吧？那你应该怎么做呢？啊，这是我们第一个版本，对吧？我们来看那么。
好的做法或者是使用了这个proxy 这样一个代理模式的做法，实际上是嗯我们再来建立一个新的。
哦。
rx. 
这个proxy 的呃有的时候是需要手工写些代码，有的时候呢在某些品牌底下啊，他常常是使用一些工具来生成。
啊，这些工具我们来看一下这个工具是怎么样的一个呃，比如说他这个工具它可以生成一个。
subject. 
啊，去嗯。
二是也是实现这个接口啊，然后当然也要实现这个类，这个类里边呢就是对。
对这个real subject。
呃，一种啊间接访问。
当然这个间接房也有可能有的，有可能会把real subject。比如说如果只是出一些安全控制的原因。
可能会把view subject 本身呢作为一个对象啊。
啊，放在这个里面。
也有可能呢由于某种原因呃，就是说比如说分布式，那这个对象都放不在这里啊，就是只能实现一些。
针对网络层的一些协议的这种控制啊啊总而言之就是说这个第九行这个地方呢，其实通常通常是不放他的啊。
假设我们放那么这个间接访问是有很多很多的东西的啊，一般一般会做很复杂。
那当然这个client 的时候呢啊真正创建出来的就是。
就是这样一个东西是吧？这是一个subject，一个proxy。
呃，我们特别需要强调的就是说这个proxy 这个设计啊。
啊，在这里这个proxy 的设计常常是在很多设计里面会比较复杂啊，就是我们说有些框架它会用自动工具来生成。
啊，但是呢这个整体的设计思想大家理解代理啊，所以代理就是大家看这个subject proxy。
就是针对real subject 的一个代理啊。呃，那我我用你访问就看起来很透明，对吧？大家看我用proxy 和。
没用proxy 之前对，看的是程序，其实都是非常接近的。当然一般来讲我们说二十二十五行这种通过某种工厂的方式把它包装起来。
你你就看不出来了，对吧？你看起来app 你去访问的时候就以为他他反正就是个i s b 结尾和一个接口。但至于它内部做了什么工作。
这就要看subject pricy 要完成什么样的任务了，对吧？是安全控制还是性能提升，还是分布式，还是也其他的各种。
特殊的原因是吧，这是说你不能直接这么干，直接调用subject，他是不合适的。
呃，proxy 这种模式就是说他看起来简单，结构非常简单，对吧？包括我们刚才写的示意性的代码都非常简单。
他真正用起来啊，可不是那么简单，对吧？他通常需要很多层面的一些配合啊。
对很多的配合，他才能做好这个事情。
啊。
好，那我们呃。
来总结一下啊，就是首先呢我们说增加一层间接层是软件系统中许多复杂问题的一种常见的解决方法。
在面向对象系统中直接使用某些对象会带来很多问题啊，作为间接层的这个proxy 呢。
是解决这些啊问题的一种常用手段。具体proxy 设计模式的这个实现方法或者实现力度相差值非常之大啊，这是我们说。
哪里呢？这个这个内部。
没有。
这这个第九行到第十一行这个内部的实现啊，对吧？就o o sorry 尔是应该是另外一个的呀啊。
啊，在这里。
就是十二行到十五号这个内部实现起来是相当的差异度相当的大啊。
但是呢嗯他的总体的设计思想是说我通我尊崇和和review 呃，就是代理类和真正的实际类型，它采用了接口是一致的。
啊，才能同一个接口。
然后从而使得客户端呢感觉上是啊是一致的。
好，那直接使用某些对象啊，那不太好。我们通过这种方式实现了什么？可能对单个对象做一些细腻的这个控制。
包括像这个copy on write 的技术啊，简单说一下啊。考be on right 的技术。实际上呢。
是呃。
简单就是他在有些实现的这个这个方式上，呃，比如说如果你的啊这个。
这这不算累啊，经常在不同的这个系统里面，字符串经常会这么干啊，就是说你如果啊嗯这个对象没有。
呃，没有什么这个更改的话的话，你你复制的话就是实际上是内部会生出一个指针指向引子啊。原来那个对象这样的话，你每复制一份。
他都不是一个深拷贝，实际上是一个浅拷贝，就是一个指针就共享啊，但是呢这个共享显然是有问题的，在什么时候有问题呢？就是当你。
需要改正的对象的时候，那就需要在内部在拷贝一份啊，这样就实现了一个啊就是一种实际上是一种代理啊就。
就是那么有些时候可能会对组件模块提供一些抽象的代理啊，这个就是抽象的带有。我们指的是像分布式是吧？在架构层次对对象。
来做proxy。
讲述分布式系统，大家以后接触到分布式系统会大量的使用代理这个模式。啊，举例来说，你要访问一个web service 是吧？这个yl service 是在比如说mr z and web service 是吧？那你防。
他包括这个web service 像现在非常流行的，像rest ice 的这种架构，对吧？那么你拿到那个rest 的接口，比如说新浪微博互奥马尔zone 或者微信的一些reset 结构。
你在c 家里面要去访问，你往往会有一定的工具，会帮助你生成那个。
那个接口的一个就是针对那个接口的一个实际的一个在客户端的一个代理的啊，那个代理的往往不是手工写的啊，往往是一些工具帮你生成。
啊，手工血非常之复杂啊，因为你要控制所有网络访问的细节啊，当然这些胆绝大多数工具是可以做到的。
那我们说那个在代理类的这个分布式呃，是系统里面代理的设计模式用于应用是机器广泛的。
那最后一点我们讲就是proxy 有的时候啊，它这个接口的完整的一致性就是严格的一致性，并不在有些系统里面不是那么的严格啊，他只要能够实现间接控制。
有的时候会吮吸一些透明性啊啊举举例来说，像有些系统里面这个字符串的拷贝，二right 的技术的实现呢，它跟字符串原有的接口并不是完全一致的。
啊。
但是anyway 他也是一种代理啊，就是在你的核心思想就是增加间接层来实现一些什么不为外界所知。
或者不为外界所类的一些功能啊，就是我们刚才说的性能的呃特殊的优化了。top 标王right 技术，就是对性能的特殊优化这样。
或者是像一些a op 框架里面啊，就面向范围编程abstract oriented programming 里边做的很多安全的控制，对吧？就是你一个方法的调用前调用后要做一些安全的这个这个控制。
或者是分布式系统里面就是代理都是这个模式都会经常会用到。
好，那我们今天这个代理的模式就讲到这里啊，谢谢大家。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br></div></div><h2 id="_16-适配器"><a href="#_16-适配器" class="header-anchor">#</a> 16.适配器</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>一、二、三、四、五、六、七。
嗯好，那我们开始我们c，dr设计模式的啊adapt适配器模式的这一讲。
嗯首先呢适配器也是属于我们接口隔离模式的一种啊呃也是一种间接思想的在某一个层面的应应用啊。
那我们说它的整个应用场景是在我们软件系统中啊，由于应用环境的变化，常常需要将一些现存的或者讲旧的对象放到新环境中使用，但是新的环境的要求的接口和这个现存的对象呢又有所不够。
那么完完美的max的地方啊，这个时候呢如何应对这种迁移？
的变化啊，拿老东西啊放到心里边去去使用。
那适配器这个模式呢是一个嗯非常非常久远的模式哈。
呃大家可以看一下这个adam ten呢实际上是来源于我们的生活，对吧，我这里呃放的一些咱们非常常见的一些adapt，这是一个水管的适配器对吧？
其实就是说那边的进水管和出水管的整个这个接口不匹配，那我们需要用一个适配器来是吗？
把不同的接口啊给他理顺啊。
然后呢再看，这边呢是一个h、d、m、i和v g a的适配器啊，就是把这个hdmi的信号转成v、ga的信号啊。
那这边呢是一个普通的电源的适配器啊，把我们比如说二百二十伏的这个电电压。
然后呢变成一些啊更低的电压啊。
呃我们生活中适配器是非常常见的，它其实的意思也就是在在对接啊或者转呃移植不同的接口的匹配需求。
那么在我们计算机里边呢啊或者让软件开发里面呢，这个同样的思想会应用到我们这个啊设计里面啊，类的设计呃非常呃常用了啊。
我们首先来呃看一下这个这个模式的定义，然后我们再写一些这样的一些代码来看一看啊，就将一个类的接口转换成客户希望的另外一个接口。
而戴夫的模式呢使得原本由于接口不兼容而不能一起工作，那些类可以去工作，这里面其实背后也有一个变。
画的这样一个cnn在啊。
呃我们可以看一下这个类图啊，呃其实这里边呢我们也是用我们之前的方法，我们来画一下。
呃首先这个target他给的是什么？
是我们未来的接口啊，或者讲是我们希望的借口，把它圈起来。
然后呢这个adpiter呢就这个adopted啊，就是被适配者啊，是我们啊这个以前的接口遗留的借口。
对，那我们都希望他们呢保持不变，啊但是我们怎么样把被适配的接口应用到新的环境里，那这个就需要我们具体。
it，is，adapt，我把它呢按照我们的规矩啊，我们仍然是呢这个列成画成这个这个蓝色，呃蓝色呢在我们这儿表示它是，但是呢它是一个变化一点啊。
呃他在这里呢我们看这个adapt这个类啊，它是继承是target。
我我们其其实在咱们学很多模式的时候都常常在强调一句话，就是继承一个类啊实际上这表明什么我遵循你这个鸡肋定义的一个接口规范，呃也就是我的aid style将具有target一样的接口规范。
那我们同时大家又看到又有一个组合，对吧？
就是有一个呃指针伸出来，这个组合指向这个ad贷。
八k啊这个▁ed，it，ion呢实际上是一个我们说组合一个。
嗯另一个类实际上是支持一个实现的这种方式啊就是一个是氦子额一个是a子蛾的关系，那么这个adpiter就实现了把adam、ten从往target这样一个转换。
啊如果我们用一些代码来表现一下啊，我们我要代码对照着我们这个可以来看一看，比如说我们在这里打开一个start的词。
嗯当然具体在这个实现过程中啊，这个attack呢实际上是有先千变万化的啊比如说我这里呢首先有一个哎他给这是我们的目标接口，比如说啊我们这里面有一个。
what？
to the world？
啊比如说这个posts。
嗯对，这样的一个一个一个函数啊，一个行为。
嗯那么我们也有，接着再来再来。
下面我们可以看一下，比如说我们还有一个i，addit。
呃这个呃单我我先没写下这个这个i。
tita呢是目标接口或者讲新接口。
然后这个advantage呢？
是是吗？
遗留接口。
或者讲老接口。
呃这里。
里面呢，当然我们也有一些它的一些相关的函数，比如说我们有一个word啊，for，然后int。
啊这个data等于零，然后what？
to？
啊再一个我也得比如说这个啊八啊然后等于零，然后它的返回值比比如说我们给它有一个返回值吧，一个int。
啊。
好，那我们说我们由于某种啊内在的这种啊实现层面的关联性，所以这个适配器你得能适配，对吧？
就是它内在有功能层面的这种可复用和可关联性，所以呢我们说是可以把advance转成一个什么i。
tried。
那在这里呢我们就去实现这个具体的东西，我们来看一下这个，我把它全。
评一下。
好啊，比如ada，paper。
那注意这里面public。
i。
track。
咱们这里讲了，你继承这个接口实际上是遵循它定义的规范，对吧？
然后呢我们这里又为了具体的这个嗯我写成protect，就是我需要一个这样的一个指针，是吧？
i。
adam就是一个组合提adobit。
啊然后呢在这个下面呢，我们可能就是在具体实现的时候，那你当然需要实现我这个process这个这个方法了，是吧啊。
哦往下往下来。
那么在在实现这个这个process方法的过程中呢，啊可能啊我这边写的是一个维码的方式，比如说p，advantage，先去调用这个把啊嗯int，a，他等于他，然后呢我再把它这个for啊这个p，fat嗯负给他这样传递。
啊这是这是一种可能的形式啊，但是实际上呢这个真正的这个转换过程是可能在某些这个这个平台里面实现，里面是非常复杂，它不像咱们这个尾码表示的这么简单呢，这是你第一，你要存在可转换对吧可转换的这样一个能力。
第二，那个转换。
过程是是相当复杂的啊，没有没有这么简单，但我们这只是用个维码的表示。
当然了，实际实际过程中呢可能这个这个接口也是比较多的啊，不是，我们这里面只有一个啊，就是通常可能是说它的其他几个接口联合起来啊呃变成你的其中一个接口。
当然了这个adam ten呢其实有那个有一些老的类，对吧？
比如说我这儿有一个o的plus。
嗯。
那么嗯这里比如说我实现了o的class呢，肯定就是他要去继承这个接口，是吧？
i。
advantage。
然后呢。
当然林林总总他肯定要去实现这些具体的方法了，这个我就不写了啊时间关系我就不写了。
总之我们就是说有这么一些老的类，他是是符合老的接口的，对吧？
嗯遗留遗留类型啊。
那么这个时候我真正去用的时候呢，举例来说，我们这个internet啊，那我在这里面真正去用它的时候，可能就是这样一种使用方式，大家可以看一下啊。
o的class，我首先呢有一个i，a，deft这样一个p。
嗯呃p，advantage等于牛。
o的class。
对吧？
尿出来之后呢，当然这个地方一般来讲，你肯定是要有一个所谓的这样一个构造器，是吧？
start的这样的构造器啊这个构造器呢传刚才这个参数就是这个p、a、f、t啊然后这个p啊darker呢等于啊这个是yes。
好，那通过这样的一个传递，我们就可以创建一个data，比如说对啊darker，当这个advance呢我把它声明成一个i。
target的接口啊面向接口编程需要我们这样去声明啊，比如说嗯就是说p他给等于new。
attract，然后呢再把p advantage塞进来。
那我就可以拿着pay tracket来去调用process，是吧？
大家明白吗？
就是我拿了一个旧的类，我从此可以拿到一个旧的类塞到这个ad盘里边，我就当做一个新的类型、新的面向、新接口的一个实现去使用了。
呃当然我们也说就是在现实实现过程中啊，这里边有一些细节可能举例来说，咱们看s、t、l啊，s t，r里边其实那个嗯stack啊和这个呃呃▁q啊队列和站其实内部都使用了一个叫d▁q啊这样一个呃advantage啊，dq就是stack和get的啊这个呃呃一个一个。
呃内部的adapt对象啊，他们都实现了，就是把它的接口转成另外一种接口，对吧？
呃当然你也可以那个里边可能没有明确的感觉是谁是新的，谁是旧的，只是说我利用它啊我利用一个老的接口啊，就dq，然后转把它转成stack要求的接口，把它转成▁q要求的接口，实际上是一个接口转换，这样把老接口或者现存接口转成一个目标接口或新接口的这样一个过程啊。
那当然那个里边呢其实没有用指针了，如果大家去看那个那个str源代码的话，你会发现它用的不是指针，他直接就把这个dq对象就就放进去了，是吧？
如果如果简单写个写个二维码的话，大家在那个里面嗯在str类里面，你。
应该能够看到这样的啊。
d▁q。
呃看天henry类似啊类似这样的一种嗯一种设计，然后包括▁q啊，就类似这样的设计，你在str里面啊、源代码里面可以看到这个。
当在这种情况下，你可能没有看到说诶这个stack它的接口是什么？
它有没有继承一个？
他他的target接口在哪里？
其实你可能找不到啊你是找不到的，因为stack本身就是既是接口又是实现▁。
q也是这样子啊。
啊也是嗯没有说你们里边就直接能够找到一个爱他给他，但它总体上符合什么adapt这个设计模式的一个一个宗旨，就是它可以从一个老的接口转成一个新的。
接口这样一种方式，所以我们很多时候也把它称为adam设计模式。
呃这就是我们常常讲的，就是大家在学习设计模式过程中啊，你不能太太死板啊太死板，在一定要追求说和g、o、f啊这个设计模式的经典定义一模一样的代码，那这个时候设计模式会啊误入歧途啊会学习的时候你你实际上会误入歧途。
我们说嗯很多设计模式的这个有很多变体形式，它不见得这个代码的这个这个整个设计上就说能够和咱们这个类图里面一一对应啊，不见了。
但是呢你最关键的是什么？
就这个设计模式它的场景和它解决问题的手法啊，以及它对变化点和稳定点的这种。
呃。
用分离方式是不是符合咱们这个模式的定义啊如果复核，那有的时候呢你会看到代码这个相差千啊嗯千差万别的，两段代码它实际上描述同一个模式，但是两段代码有的时候非常接近，你可能甚至不觉察的话，你会觉得就是看不出来他们的特别明显的区别，但是他就一点点的区别，它就表明他他这个是那个模式，那个就不是那个模式。
所以就是这是设计模式最有艺术，也是最难掌握的部分。
就是说大家不能用一种非常死记硬背、非常死板的这种这种方式来去理解理解它、去去记忆它，而是需要上升到一种设计原则和设计手段的这种啊灵活运用上。
好，那我们简单做一个总结啊。
首先呢adamson模式主要应用于希望复用一些现存的类，但是接口又和复用环境要求不一致的情况，在遗留代码复用、类库迁移等方面非常有用啊几乎啊你大家去看一些这个你你如果看这个软件行业的很多这个frame啊，那么你经常能够看到啊各种framework里面都有这种ada。
paper，它常常都是在处理一些迁移的这种这种需求。
那j、u、f在这个呃最经典的这个这本这这设计模式这本书里面呢，它其实定义了两种adam模式的实现结果，一种叫对象适配器，一种叫类适配器。
嗯我们刚才讲的实际上是对象适配器，呃主要区别点在哪里啊？
实际上就是我来对着代码。
说。
嗯那这个叫对象适配器，主要是组合了一个对象。
大家看二十一行，就这个我们说是一个组合啊，然后这个地方是继承。
对一个集成，一个组合，这个就叫对象适配器。
因为它是通过组合对象来实现的。
但是也有啊一些啊adapt，就是j、u、f定义的这个第二种呃适配器呢我我在这儿写一下啊，我先把上面写下，这个叫嗯对象适配器。
啊还有一种叫类是。
自备器是这样干的。
哎对，他是在这儿，然后呢一般会这儿写一个for，text或者是private啊然后把这个i，str、ten，放放进来。
这个可能有些人还不太理解哈，或者就是诶为什么可以这样？
其实这两个很接近在在内存模型上非常接近。
这次我们想想，有时候你都看不出它的区别。
这个是什么？
多继承，对吧？
这我记成了俩啊。
诶。
我把这个这个放在这里啊，这是多继承的方案啊，当然一个一个是它的公有接口。
咱们知道public继承是公有接。
接口，对吧？
就是说我符合你的接口规范。
pro猜这个继承实际上我们叫实现继承或者private继承，都是实现继承，就我并没有继承你的接口，但我用你的实现。
那么这个这个做法啊，这这类适配器呢其实不太好不太好。
呃就是说它有很多很多一些其他的一个困扰的问题啊，就是大家知道其实你你继承这个i，adam，terminal，wanna，city是是不够的，是吧？
为什么？
它是个它是个虚的，对吧？
它是个纯虚的接口，那么他他们也没有实现，那你把old cast怎么放呢？
所以你这样做的话其实只能怎么干呢只能这么干啊，就是你这个继承i。
ada其实是没用的，因为那是个存续接口，对吧？
你自己内部还要去实现它。
那么通通常有做法就是说嗯那你把它换成这个，但是这个之后呢带来的问题是什么？
就你定死在这个类上啊，它没有灵活性啊。
然后这个这个有灵活性大家有没有看到这个这个接口是相当有灵活性的，对吧？
我今天可以指向o，data，我明年可以指向android。
class它是一个指针啊。
啊呃这里面是一个类，类就定死了，类就是作为父类，我们常常说继承啊，继承给你带来很多静态的这种复用特质，其实就是这个意思，就你没有什么灵活性，对吧？
你一进入这个了，定定死，你永远复用就是它的函数实现。
但是这里不一样，这里就有很很高的灵活性。
呃其实就是大家反过来说啊，你去学习设计模式的过程中啊，嗯。
呃会反过来帮助大家去梳理你对于多态、继承、组合啊呃、动态啊这些核心理呃机制的一个深入的理解啊。
呃其实当你掌握的这些设计模式之后呢，你再看继承啊，我相信大家呃就是跟你没有学这些设计模式之前，看的这个继承的这个观点就不一样了，你对他的理解就上了另外一个层次了。
好，我们再回到这个ppt上啊，就是类适配器是采用多继承的实现方案，一般不推荐使用啊而且这个这个放到其他语言里面，比如说像这个咱们讲话语言say，shop、swift这些语言，是吧？
都他都不支持这种他他他类不支持多继承，它只是接口的多继承啊所以。
我们说今天来讲啊，类适配器已经用了很少很少啊，几乎可以这样讲，类似废气只有坏处没有好处，对吧？
你在c加加里面也是如此，你你直接换成对象识别器多好。
而对象识别机采用组合的方案啊，呃它更有松偶和的这样一个一个一个一个特点。
好，那最后一点我们也说一下，action模式可以实现的非常灵活，有的时候不必拘泥于g、o、f定义的那种那种经典结构，对吧？
就像我们刚才说那个stack和和和和d呃▁q对吧内部用的这个d▁q啊这个这个都是呃不是不是像像以前那么那么啊这个这个结构那么那么的死死的啊有有很灵活的实现方式。
甚至有的时候呢，比如说我们这里，你不必不一定说那个那个指针，一定。
放在那里面，你甚至可以放做一个方法的参数啊，都都有可行性。
好，那action模式呢我们今天就谈到这里。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br></div></div><h2 id="_17-中介者"><a href="#_17-中介者" class="header-anchor">#</a> 17.中介者</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>嗯。
好，那我们开始我们最佳设计模式made direct。
啊，中介者模式的这个这场讲座，中介者模式也是我们的一个接口的隔离模式。啊，那我们来看一下这个模式解决的问题啊。
在软件构建过程中啊，我们经常会出现多个对象互相关联交互的情况。
对象之间呢常常会晤为期一种比较复杂的引用关系啊。
如果遇到一些需求的变更的话，这种直接的引用关系将面临不断的变化。
嗯，我们举一个例子啊。
谁说大家啊可能经常需要考虑呃一种情况是界面，比如说你你界面上有非常多的一些控件。
这个时候呢，通常大家希望更改界面的这些控键的这个状态的时候呢，你对应背后可能有你的数据的data model。
对吧你改界面的这个时候呢，你的date model 希望也跟着更改。啊，那反过来呢，有的说你希望你更改这个data model 的时候呢。
你希望你的界面呢也跟着更改，对不对？
那这种两种情况呢有时候就会导致啊。
出现一种所谓双向的依赖关系。
啊，或者直接的依赖关系。
啊，比如说你一个一些界面的这个元素啊，里边可能啊就是就是要直接去引用你的鞋date model 啊，数据对象。
反过来，如果你的数据对对象的更改呢，你也想直接的去啊引用这个界面的元素啊，这是可能会出现的一种情况。那我们说这种情况。
当然不合适对吧？如果你想一下这样的引用关系，他的这个需求，任何的这种变化给你换一些界面元素的话啊，这个这个成本非常之高。
那这个时候呢，我们是中介者模式给我们提供一种思路啊，他来管理对象间的这个关联关系。
避免相互交互的对象之间能解耦合啊。
呃，从而来抵御我们这样的一个一个变化的情况。
嗯，我们来看一下这个模式的定义。
首先呢我们讲的是用一个中介对象。
啊，来封装。哎，这个封装呢其实我这儿勾了一个关键词，叫其实是封装变化的一次。
封装一系列对象的交互。
啊，中介者使得各个对象不需要显示的应用啊。
所以显示的。
显示的引用是一个什么意思啊？就是编译时依赖。
对吧，当你产生了编译时依赖的时候呢，这个就不利于未来的变化。
那我们希望把它转成什么运行时以来。
就依赖总是要依赖的，对吧？因为你最后要比如说a 对象啊，这个这个写的行为要导致b 对象一个什么样的一个一个一个结果。
这个时候呢，你总是要产生一个依赖关系的。但是我呢我们不希望编译取以来，我们希望转成运行之一了。呃，这是我们很多设计模式里面的一个技巧。
啊，比如说我们最经典的依赖倒置原则，a 本来是依赖b 的。
啊，我们把它转化之后是a 依赖ibb 依赖ib。但是难道a 在跟b 重审没关系了嘛？也不是的。如果你仔细想想的话，你会发现运行是a 和。
这个b 还产生了一个依赖关系，只不过这个关系被我们从编译时转到了预警式啊。
从而使其松散耦合。
所谓松散耦合，就是我们能够管理变化的而独立的改变他们之间的交互。
我们来看一下gif 的这个定义啊。
其实这个定义相当粗糙啊，或者是很容易啊把人带到沟里。
啊，在现实中，呃，比如说大家看这个图的话，其实你呃如果没有配套的其他理解的很难看懂这图这幅图的。
这个这个解决问题的核心要义在哪里啊？比如说这个mediator。
嗯，他是定义了一个中介者啊呃这个中介者啊啊我们说这个college 大家注意这这里面如果我们稍微画一画这个关系图的话。
像这个。made it at her. 
her college. 
对college 内部有一个指针指向了啊mediator，对吧？然后呢这个concrete made it hr 注意啊。
它里面又有指针，可以再看这个指针，我把它圈起来了。
这个指针。
这个指针。
还有这个指针啊，康奎的minature 里边又有指针指向了具体的一个一个的college。
啊。
嗯。
所以这里边的最核心的关系是什么啊？呃是college 之间没有依赖关系。就大家看college concrete college 一。
和康rage college are。啊，这两个对象之间是不依赖的，本来是应该直接依赖啊，现在不做到直接依赖啊。
嗯，那么他们都去依赖谁？一旦mediator。
然后反过来呢，梅林辰内部呢也要去依赖嘛这些college。
所以这个meditator 和college 之间是一个双向抑的依赖关系。但是college college 之间呢将不再产生任何依赖关系。
这是我们通过这样一种方式。
达到了一个依赖的杰作。这幅图的本质其实只是描述了依赖杰。
并没有描述任何其他的东西，甚至那个康quit college。一继承那个college 康瑞college 二g 成那个college 在现实中间。
常常不是这个样子的啊，或者讲就是concrete college 一和count college are 他两个这个这个之间的关系啊就是。
常常不是体现出继承某个某个子类啊，当然他表现有时候会采用一些公共接口是ok 的。
嗯。
我们来画一幅图啊，再来梳理一下这幅图描述的关系。我觉得呢更能帮助大家在现实中间去掌握和运用这个设计模式。
那我们这边呢？
我们调出一个白板。
我们来画一个。
刚才我们说的一个关系，比如说我们现在这样一个对象啊，一号等一下。
啊。
二号等一下。
然后再来一个，比如说三号的。
嗯，再来一个四号的。
嗯，再来一个五号的去。
好，我们说呃如果你不加约束的话，那么你要想实现他们之间的一个访问关系。
你很有可能，比如说你一需要防三。
啊，二需要防三。
啊，然后呢，就说二需要访问四。
然后呢。
五呢需要访问二。
然后五那学方面一。
啊。
比如说你的依赖关系呈现这样一种这种关系。
我说这个呢不太好是吧，呃，因为它产生了非常直接的各个对象之间直接的依赖关系。
那我们希望呢提出一个新的对象。
来解耦他们之间的依赖关系。
这个时候呢，我的这几个对象还在那里啊，比如说我的一号对象还在这里啊，二号在线呢还在这里。
这个一二三啊四五都是咱们刚才的说的college 啊，三号对象在这里。
然后呢，四号对象呢在这里。
然后五号对象呢在这里。
好，那我之前的依赖关系呢，我希望把他新的一个一个一个变化我。
换一种颜色，用蓝色来表示。
你说呢，这边我用蓝色呢。
我写的m。
这个m 呢表示我们的media 啊就是我们的中介者。
好，然后我让一呢。
跟中介之之间啊产生双向的依赖关系。
二呢和中介者之间产生说这样的依赖关系。
山野如此。
啊，事业。
我也如此。
啊。
好。
当我定一下这个之后呢。
以后当我需要，比如说eg 一去呃呃发消息调用三这个对象的时候呢，我不要直接的伊去掉用伞。
而是说一先通知m。
而m 在通知三。
啊，当然这个过程中就要牵扯到一个这个调用通知，要定义一个调用通知的消息规范。
是吧就你发给m m 怎么才能知道这个这个消息规范是要去找三了。
啊。
所以那你必须要做这样的一个一个消息通知的一个规范啊，这个实际上是上边咱们这个mediate 设计模式啊，就是gf 定义这个图里面说没有定义你怎么实现这个项。
当灵活了啊。
呃，举例来说，在很多这个系统里边有这个所谓的数据绑定的模块。
啊，就是我们刚才描述的一种情况，这界面元素和数据模型，这间不希望产生直接依赖，所以常常提出一个数据绑定类型。
就是我们这里面讲的这个m 啊数据绑定类型呢。
呃，他会同时依赖啊两边对吧？同时依赖见面元素和同事依赖数据模型。
呃，当然有的这个呃数据绑定模块会加一些什么？加一下咱们叫做这个嗯啊观察者模式的一些元素啊。
呃，在在里面，这样就实现了你数据模型只要一变更，那我都不用去做任何的主动的操作。那么这个这个绑定的对象就知道。
就得到一个触发消息，这个触发消息直接就去找那个见面，说去更改那个界面元素。
啊，那么比如说常见的数据绑定元素，呃，这个对象里面就会定义一套这个对象绑定呃的一些协议。这个协议其实最后就会转化成他对象互相通知的协议。
就是你的对象的嗯，比如说对象的这个这个这个id 还有呢对象的什么这个呃具体的属性。
啊，然后属性值，然后你的这个。
嗯，home 键，比如说你控件的这个呃这个这个这个属性以及控件的属性值，还有哪个控件啊，这些呃要需要传递的相关参数啊，作为一种一种协议来通知。
一定要定义清楚。
这是咱们media item 设计模式啊，gf 定义的摄影模式不会不会去触及这些细节的。但这些细节在你实现这样一个模式里边啊，又是。
一是设计的啊非常非常繁琐的地方。
呃，那但是千差万别啊，这里边有千差万别的实现方式。但是宗旨是什么？就是大家看。
左边这幅图能不能转化成右边这幅图？
啊，也就说你能不能把以前你直接依赖关系变成一种间接依赖关系。啊，大家看一和三之间没有直接依赖关系，一和三都是和m 产生关系。
啊，这这个模式也是一个相对来讲我们像发射的一样，对吧？嗯，他跟发射的其实异曲同工，大家体会一下是吧？异曲同工。
啊，都是隔离，都是通过一个新的东西提出隔离啊，但是呢发散的解决的是什么系统外。
与系统内的之间的这个隔离。而中介者呢解决的是什么？系统内各个对象之间的隔离。
呃，但是我们也强调啊，就是中介者设计模式的应用一定是出现了大量的啊。
我们来看一下啊。
就是大量的这个这个这个系统内复杂。我们这里有一句话叫做啊经经常会出现什么。
多个对象互相关联交互的啊情况啊，然后出呈现一种复杂的引用关系。
这个时候你才去提出中介者如果就那么一两个，对吧？他的病，他的整个这个引用关系又不那么复杂，那你实际上是没有必要去提出中介的。
甚至咱们可以说中介者设计模式呢是咱们之前依赖倒置原则，在多个对象场景。
的中的一种扩展形式。
对吧，依赖倒置原则讲的是什么？本来是a 依赖b 的，现在不要了，现在ae 赖id 然后b 依赖ib 啊，那么中介者模式呢实际上是把这个a。
不只是在处理a b 之间关系啊，而且a b c d e f g 是吧？很多对象这样一来关系，但是呢这个有一个前提就是说。
你必须出现密集的大量的这种复杂的交互。
但这些都是定性而非定量。什么叫复杂？什么叫大量是吧？这个量多多少才能用啊，这个是需要大家自己去根据自己的设计的，是牛肉来去。
判断就是你的变化的幅度是不是足够的多。
好，那我们来对中介者设计模式做一个总结啊，将多个对象间复杂的关联关系解耦。
啊，made it at 模式呢将啊多个对象间的控制逻辑进行集中的管理。这个集中管理我刚才讲了，其实背后他是小。
啊，往往在实现细节上，你需要定义一套这种所谓呃这个调用机制的一个呃协议啊，便多个对象互相关联为多个对象和一个中介者关联。
简化了系统的维护啊，抵御的可能的变化。那随着控制逻辑的复杂化啊，made date 具体这个。
啊，的对象呢实现可能会相当复杂。呃，你就是你那套协议的订阅啊，这定义这个时候可以对made date 对象有时候会进行一些分解的处理。
呃，刚才我们也谈到了first 设的模式啊，是解耦系统间的对象关联关系。而mediator 模式呢是解耦系统内的各个对象。
现在关联关系。
好，那media 的模式呢讲到这里呢，我们其实这个小专题就是接口隔离模式啊，这四个模式都讲完了。
大家来回顾一下这四个模式啊，是不是跟咱们说的这个接口隔离这个四个关键字非常之有关系。
对吧，这也是我为什么把他们四个啊呃用用我的啊所谓理事归类法啊，我把它归到这样的一个类别里边，而没有按。
gif 的那种归类方法。
因为我觉得这种归类方法其实呃可以对大家去梳理他的这个这个理解和掌握更有帮助。
那么我们再来回顾一下发散的是解决什么系统呃，内和系统外，对吧？proxy 呢解决的是什么？
俩对象啊本来是可以直接依赖了，但是由于某种特殊的原因，性能的原因，安全的原因，分布式的原因等等。
所以必须隔离，必须拆开，拆开之后就需要啊本来a 访问b 的对吧？现在不要了，现在建立b 的一个proxy。
一个代理a 去访问b 的proxy，然后be the proxy。在内部在实现对b 的那些分布式、高性能、安全等等的一些细粒度的控制。
然后呢完成对b 的一个使用或者调用。
i adapt 呢是老接口和新接口的一个不不match 的情况，对吧？你需要把它match 进去。那么这个时候呢你需要对老接口呢进行转换。
啊，那建立一个adapter 类，让他去继承你的新接口。i target it. 然后让他去组稿接口，然后你再去。
那个实现里边呢再去完成这个老接口的核心接口之间的转换逻辑。
嗯，many at 呢刚刚讲过对吧？这个就不再不再赘述了啊，那这四个模式呢。
他就是对接口在整个这个演化过程中，在不同方向不同角度的隔离啊的一种需求。
啊。
呃，如果你把这四个模式多坏话的图多想一想，你会发现啊异曲同工啊。他都是在玩转这个接口隔离这样的一个核心的思想。
好，那我们maitter 设计模式呢，今天就谈到这里。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br></div></div><h2 id="_18-状态模式"><a href="#_18-状态模式" class="header-anchor">#</a> 18.状态模式</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>好，那我们开始我们新家设计模式，state 状态模式。
来看一下呃状态模式呢，我把它和这个mm to 能归到一个新的类别里。
我们这个类别叫状态变化啊。
那我们说在组件的构建过程中啊，某些对象的状态经常面临变化啊，如何对这些变化进行有效的一个管理。同时呢又维持高层模块的稳定。
啊，对于我们又回到了什么管理，什么稳定和变化的这套模式里面。
哎。
是吧那么状态变化模式呢啊为这个问题呢提供了一种解决方案。我们首先来看下state 状态模式描述的一个问题的场景。
我们讲在软件构建过程中，某些对象的状态如果改变它的行为也会随之发生变化。
啊。
比如说我们文档啊处于制度状态的，你的行为啊和读写状态的行为呢可能会完全不一样等等啊。那这个时候呢我们如何在运行时。
根据对象的状态来透明的更改对象。
所以这几句话呢，我们来看对照代码来说会比较有这个。
呃，更清晰的一个理解。
呃，我们假设我们有一个网络的一个应用啊，这个网络应用呢它会根据网络的状态做一些调整行为上的调整。
呃，比如说我们网络上有三种状态啊啊打开关闭连接啊这么三种状态。然后我们这样一个网络的应用呢。
他就放了这样一个状态是吧？
呃，那么针对比如说我们有一个操作这个操作，当他在打开的状态记下的时候，他要他的行为是不一样的，对吧？
这样一种行为。
呃，然后呢，当然他执行完毕之后呢，它的状态要变成比如说从打开转成关闭态。
如果他之前是关闭的状态呢，他做这个operation 一的时候呢，他就要经过一些呃其他的操作。然后他的。
状态变成这个connect 连接它。
如果他之前是连接态的话，他经过这个状态之后呢，操作一些其他的操作之后，他会变成open time。
呃，就类似啊零年年中呢，比如说operation 二啊，就是另外的行为也是会呈现这样的特征。如果他之前是打开泰是吧，他经过的操作也是不一样。
啊，等等这样的一些做法。
嗯，这里面呢最关键的就是大家来看啊，对照二ppt 我们来看一下就是。
对象的状态如果发生改变。
他的行为也会随之变化。
对吧这个这个acl s 其实已经很清楚的表明了operation 一是根据你的状态不同而行为不一样。
当然在这个过程中，他会改变他的状态。
对吧，不断的因为一些操作在改变当中。
那我们这样写有什么问题？
呃。
有有一些朋友，如果有一啊稍微有点印象的朋友，大概现在可能会意识到，诶，你好像好像这段代码。
似曾相识啊。
找货。这个问题是很相似，大家想一下哪个模式啊？
我们之前讲过了啊。
strategy 是吧。
啊，是策略模式跟这个模式呢。
从这个特点来看啊，几乎是人你能发现问题是一样的。
就是我们讲的。
一个sls 的bad smail。
对吧，出在你的代码里面出现了很多a f l s。
而且这个a fels 呢。
它是有关一个业务状态。那我们我们a strategy 设计模式已经告诉了我们。
啊，对，这种情况，咱们要问一个为什么有有设计模式的素养的朋友，应该问一个啊，哎我这个。
以后这这是个枚举类型，对吧？那这个枚举类型以后会不会有其他的类型出现？
也就是你有没有会不会有其他的状态。
如果我这里面添加了一种新的状态。
呀。
假假设啊我这里边添加一种wait 这样一种新的状态。
那么我这个之前的代码要怎么更改？
那。
大家想一下，如果添加wait 对吧？那你这个后边的这些代码是不是。
第一呢要补lsa f 是吧？
要在这里补l sf 啊，然后当然你的有些状态跟这个wait 之间啊呈现一个什么样的转换关系，然后做一些处理。
呃，但这这样的一个做法，显然我们说。
是一个违背开闭原则。
啊，所以开闭原则就是你的需求的变更。
导致了你要在你的很多代码里边不断的去改这些地方啊，不断去干。
所以我们说这个不好，对吧？那好的做法是什么呢？
其实。
呃，咱们一旬这个strategy 模式给咱们的一个设计的经验。
啊，我相信有些朋友应该也想到了。
抽象类是吧，先提抽象基类。好，我们起一个抽象基类。
啊，class, that works state. 就把枚举类型，而以前的枚举类型。
转换成了一个抽象基类。
然后把以前的操作就是所有跟状态有关的操作啊，而不是任一operation 二可能还有什么二三等等啊。
全部变成状态对象的行为。
啊，我求的啊，而且要要用多态，对吧？也就是用虚函数来表达。
好，当放到这里边之后呢。
在塞一个这样一个状态对象的指针。
啊，状态类型的指针放在这里。
嗯。
当然你作为一个激烈要支持需吸构函数是吧啊，就是挤压的一个要求啊。
好，然后有了这个之后呢，我们设计open time。
open 呢这个注意是我们前面曾经讲过的这个singleton 的设计模式。我们我们在这个状态里面其实倾向于大家要用这个single。
啊，因为因为这个对象没必要有多个啊某一个状态对象结合有一个就可以了这个。
嗯，大家知道就可以了啊，然后我们再来看operation 一。
啊，我们现在offer 之一呢，当然一般意义上啊，这个二零一呢跟这边offer 以肯定是有差别，就是跟这个里边是有差别的。
呃，所以差别就是你收集参数啊什么你可能需要带一个context 的上下文参数，然后得到这些参数之后对他进行处理。
但是这个处理的核心逻辑就是二十六行核心逻辑核实强行核心逻辑是类似的。
然后呢，你这个状态呢。
有一个字段赋予我们状态里面有一个字段啊。
有一个啊这个字段是放在前面几类里面。
这个next，he next x. 
当然我这里面啊为了方便演示的原因，我直接设计成公有字段了。实际大家开发的过程中还是应该遵循我们的一些设计的一些要求说。
啊，甚至私有字段，然后设置公钥的接口，get set 方法来设置，对吧？那我这里就省院那个过程啊，然后咱们p next 等于。
执行完之后对吧，等于就是我经过operation 一，我这个状态就换成closed time 了，但是注意我换成close time 的时候，我换的是一个对象。
我可不是换了一个枚举啊，换了一个对象，这close 就是singleton 的调用方式，对吧？
然后同样的operation 二的时候，我的下一个太换成了啊connect。
如果而不是三的时候，我的下一个太换成了open time。
呃。
总而言之就是我在这里呢是根据什么把状态相关的操作啊。
全部编码到一个状态对象里边啊，那就是只要你是open time 的时候。
比如说如果是open 的就是这一段代码啊，实际上是一到这儿啊一到这里。
啊，然后呢。
connection time are operation seven. 我当时没写这边那一类似了，就放一段把你在。如果你是你是open time。
而且执行的是operation 三，你应该执行什么样的行为？然后你执行完之后，你的下一个状态会切换成哪个行为啊，就切换成哪个状态，把它换过来就可以了。
啊，这是open time 啊，那以此类推的啊，我就不写了，就是close time，大家也可以去写，对吧？
你的closed state。
仍然是需要继承这个什么。
然后of state。
是吧既然是在这里啊做相关的工作啊，然后呢当然我们说这里接着呢你这个connect time。
啊，等等，你都会这么做啊。
呃，那我就不写了，我就用省略号来表达。就是在这里边呢，其实你需要做。
呃，各种状态对象啊。好，然后接着我们这个网络应用被改写成什么样子的，我就塞了，就不是一个枚举。我之前塞的是一个枚举的。
字段对吧？现在呢我就是一个真正的这样一个状态对象啊，这个跟咱们strategy 模式处理的手法异曲同工。
是吧然后呢当然你在这构造期需要去初始化这个cast date。
然后operation 一做的时候，我前面就去做一些收集参数啊等等那些工作。然后拿到之后呢，把这些参数呢，我到时候就其实是传递给。
可以，这个我都省略了啊，我们只要来看这里。好，首先调用p state operation 一。
那大家想想这个跟这个。
实际上是变了一个法子而已。但是呢在背后的调用的结果是不是一样的。你想一下这个这个地方，其实其实这句话啊，六十二行，我们说虚函数的本质啊。
背后其实就是一个运行时的e c l s 是吧？
嗯。
就他这运行时，他会判断这个p state 这个这个指针如果指向的是一个open time，那么它调用的就是open 上的open 状态的那个。
office 一是吧，就是这一段。
如果pc 的指向的是一个class 的状态对象，那么他调呢是不是就是这个excel s close the 这个情况底下的operation 一对吧，就是这一段。
所以他调用的结果，大家如果用一些salt 的方式，对吧？你在命令行输出一些东西的话，你其实可以验证这个结果是一样的。
啊。
然后呢，执行完之后，我就让他的状态等于它的下一个状态。
所以这个下一个状态。
是什么是p state operation e 自己。
啊，他内部刚才我们不讲了，而不是以内部他会更改把他的下一个状态指向。
哎。
自己所需要的那个状态，对吧？
那我不用管我。that office 呃，这个network processor 我这边过，我永远指向就是换他下一个状态就可以了。
p cate 永远等于他的下一个状态。
好，那operation 也是这样的，类似的做法。
啊，阿山也是啊。
那当然这样做了之后，大家想一下好处在于什么？
跟咱们strategy 模式的好处是不是异曲同工啊，一样的对吧？就是当我们状态增加的。
大家想一想，假如我们现在就像我们刚才举例子来说啊，这里面增加了一个。
啊啊，wait 的状态。
啊，比如说我这里面增加了一个wait。
对。
这样一个状态。
这个是集成。
啊，那我仍然是这样的一个做法是吧？我在这里就就去继承他了，然后去写wait 状态里边的operation 的一些东西。
是吧那大家想想这个network processor 这里边要不要变啊？
大家想一下不用变了是吧？因为我我我不关心你是什么状态，我永远关心的是。
你状态的上面的行为只要是对的，对吧？当你是状态是wait 的时候，那你offer 是一是个什么行为？
那当然是你自己在那边负责，已经实现了，对吧？你刚才去去去继承这个子类的时候，当你的下一个菜，你自己在内部一样的像你。
像你open 太一样指定对吧？就是说你的下一个看是谁，你自己制定就此状态行为里边自己去管理自己的状态的。
这样一个转换关系。
在我network processor，我只知道你有这样一个状态就不对。至于你的下一个状态是谁？
我不关心啊，我永远就这样换。
那大家想一想，这个是不是就达到了什么稳定了。
啊，相对来讲就是你以后的变化都是在什么，在这里扩展子类。
啊，这是一种。
扩展的方法。
是不是？
或者啊。
这是一种扩展方法是吧，就一个。
就子类继承就是一种扩展。
啊，我就不需要更改源代码，我增加子类就是。
啊，然后你原来的这个net processor 仍然运转良好啊。
好，我们回到旭季啊，我们做一个总结来看一下啊。
大家看c 设计模式，允许一个对象在内部状态改变的时候，改变他的行为。
对吧，就是你的状态改变啊，你的行为跟着就变了。实际上这个里边内部使用它是多态的这个。
从而使得对象看起来似乎修改了其行为。
啊，我们可以来这里面看一下这个类图的结构。
这个state 是吧，跟跟rated 是真的非常像。这这这里边当然这个它里面放的是一个行为，对吧？我们说。
也有可能是一个行为，有可能一般状态大多数情况是多个行为啊，实际上一个行为的时候跟thread 去没什么两样，是吧？
啊，那么。
大家看这些子类啊，是吧，这这这俩之类也是啊，就是他的不同的状态啊处理的行为，这个实现的handle 就不一样。
那么这个这边呢就是我们的这个context，就相当于我们人that to work processor 是吧？
啊，这里边是一个什么是一个指针是吧？这个抽象。
所以如果我们画这个图的话。
啊，还是用咱们之前讲的啊，这个哪些稳定啊。
这个是稳定的是吧？
啊，这个也是稳定的。
是那变化呢，我们用蓝色蓝比蓝色的笔颜色比的话。
这边在变化。
对吧？
就是还是你要看出来这个类图里面哪些是稳定的，哪些是变化。
好，我们做一个总结啊，首先z 的模式将所有与一个特定状态相关的行为都放入一个c 类的子类对象里。
那就operation she 啊，不是是二，而不是三全部塞到那个。open the state 里面，对吧？在对象状态切换的时候，切换相应的对象。
啊，但同时维持state 的接口啊，就是你接口是不变的，对吧？都继承。networks are state. 
这样实现了具体操作和状态转换之间的一个结构。
那同时这带来另外一个好处啊，就为不同的状态引入不同的对象，使得状态转换变得更加明确。
啊，可以，而且可以保证不会出现状态不一致的情况。因为状态的整个转换是个原则性。
呃，简单来说呃，我我我我我office state 我只关心我三个操作之后的我的下一个状态是什么？
对吧我不需要太多的啊去去想这个跟他更多耦合的情况啊。大家可以想一想一下，你你在这个情况下啊。
二分之一写了这么多a f l s 对吧？哦。
然而不认识。二u e 对a fs 那这个状态转换之间的关系是真的是非常非常乱啊，但这边呢容易剪，把它简化了，对吧？
当我想open state 的时候，我只关心，而不是一执行完我的下一个状态是什么？
他分之二执行万物的下一个状态是什么，operation 三，肢体啊执行完下一个状态是对吧？我就很清楚。
就是我只关心我的后继碳，我不用关心再爱往后这样活啊，其他什么这之类乱七八糟状态。
啊，这个就是状态的之间的一个转换关系啊，但最后一点就是我们说如果state 对象没有实例变量啊，没有就没有。
除了那个后期碳之外的其他二十一遍，我们上下文可以共享一个state 啊，其实就是我们这里讲的这个用用了什么用了。
呃，咱们这个single 啊就是singleton 的模式，使得你整个这个对象的生存周期管理比较简单，当然也节省了对象的开销。
呃。
对c s 模式呢呃我们讲下来大家会发现和strategy 模式真的非常像是吧？非常小。
嗯。
呃。
我也想说一下，就是大家以后就选我们设计模式啊。你你往回看啊，我们最后一节课会带大家往回看，又往回看的时候。
你慢慢会发现很多模式越来越像越来越像。
你会发现这一点啊，大家会发现这个就。
为什么他们越来越像了？这是你看的不同的角度啊，我现在这里卖个关子啊，大家多注意去看一看。哎，你可以尝试把你的这个。
这个每一个设计模式的类图找出来啊，比如二十三个设计模式的类图，全部整呃摆在你的面前。
去观察他们去想一下这个类图之间不同点在哪里，相同点在吗？
你很快发会发现他们相同点越来越多啊。
这就是我们说学习模式呢，你最后在你的眼里你会发现哎这些模式之间的。
这个会变得更平坦，差别变得更平坦。
甚至于来讲，你你可以把这个模式具体的名字给他忘掉。
对吧？
就像就像我们说state her streng。
去解决的手法都非常非常类似啊。
你你甚至不必太过于计较他们之间那种差异性，而更关注他们，他们到底解决的是什么样的一个稳定点和变化点。
关系的问题。
这个时候呢，其实模式之间的关系也理顺了啊，就学学习模式就不那么生搬硬套，就非得有些朋友经常犯一个错误就。
得追求数量是一定要告诉我这个模式是什么。我写的这段代码是不是那个模式？
其实今后在大家的工作中，慢慢的你会发现啊。
他这个模式叫那个名字或者他的差异性不那么重要啊，他无非是一种设计上的一种演化而已。
是一种松耦合设计的原则的演化。
呃，叫我说啊，你甚至可以把state strategy 看着同一个模式。
你在你眼里刚刚看的一样啊，就是出现了问题，什么问题？f a l, s. 
没举啊，我怎么转用多态的方式来实现运行时的改变。
啊，你掌握了这个，那具体它是什么模式，真的在实际的开发中没那么重要。
好，那我们今天的这个state 呢，我们就讲到这里啊，就多对比，多总结很重要。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br><span class="line-number">177</span><br><span class="line-number">178</span><br><span class="line-number">179</span><br><span class="line-number">180</span><br><span class="line-number">181</span><br><span class="line-number">182</span><br><span class="line-number">183</span><br><span class="line-number">184</span><br><span class="line-number">185</span><br><span class="line-number">186</span><br><span class="line-number">187</span><br><span class="line-number">188</span><br><span class="line-number">189</span><br><span class="line-number">190</span><br><span class="line-number">191</span><br><span class="line-number">192</span><br><span class="line-number">193</span><br><span class="line-number">194</span><br><span class="line-number">195</span><br><span class="line-number">196</span><br><span class="line-number">197</span><br><span class="line-number">198</span><br><span class="line-number">199</span><br><span class="line-number">200</span><br><span class="line-number">201</span><br><span class="line-number">202</span><br><span class="line-number">203</span><br><span class="line-number">204</span><br><span class="line-number">205</span><br><span class="line-number">206</span><br><span class="line-number">207</span><br><span class="line-number">208</span><br><span class="line-number">209</span><br><span class="line-number">210</span><br><span class="line-number">211</span><br><span class="line-number">212</span><br><span class="line-number">213</span><br><span class="line-number">214</span><br><span class="line-number">215</span><br><span class="line-number">216</span><br><span class="line-number">217</span><br><span class="line-number">218</span><br><span class="line-number">219</span><br><span class="line-number">220</span><br><span class="line-number">221</span><br></div></div><h2 id="_19-备忘录"><a href="#_19-备忘录" class="header-anchor">#</a> 19.备忘录</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>好，那我们开始我们自己家设计模式，memento 备忘录设计模式。
呃，备忘录呢在咱们呃其实也属于一个状态变化的模式啊，他跟state 模式呢呃我们都归到这样一个。
呃，跟状态有关的一个类别里面。
我来看一下备忘录呃，解决的是是一个什么样的问题。他主要在软件构建过程中某些对象的状态在转换过程中，可能由于某种需要呢。
要求程序能够回溯到对象之前处于某个点的状态。
啊。
那么。
比如说你做一些对象级的锐度和安度的操作是吧？如果使用一些公共接口，让其他对象得到这个对象的状态会。
暴露对象的实现细节。
那么备忘录的主要是在解决，就是我维持啊这个嗯封装性的前提下，怎么样实现这个对象的状态。
呃，我们先来看一下啊这个模式的定义在不破坏封装性的前提下，捕获一个对象的内部状态。
然后在对象中外对我们在强调啊在对象之外来保存这个状态。
这样以后可以将该对象恢复到原先保存的状态。
好，那这个。
意思我们大概了解了，我们看一段适应性的代码来看一下。
比如说这是一个啊典型的这样的一个备忘录的。我们先来看啊这个这个部分假设。
这个对象啊。
是我们的一个嗯。
一个一个所谓我们需要保存它状态的一个对象。
呃，他的状态可能有很多啊，我们这里面当然就是试听的代码，就是只放了一个字符串state。但是它可能啊我这里用省略号来表示它有可能有很多很多的。
内部的状态啊。
嗯，那么这个对象呢，我们有一个需求，就我们在某些点的时候呢，希望把它状态呢。
给他拍一个快照。
啊，还有一个对象的这样一个内存快照状态，快照存起来。
那怎么做呢？就是我们设计了另外一个对象，这样一个member to。
而他的状态内部的表示呢。
和这个是对应的。
和和这边是对应。当然在现实过程中，现实的实现过程中，这个状态有可能啊只摘取他们某些有效的状态。
就有些状态呢是不需要啊做快照的对吧？你就不需要放糖了啊，而且在实践上有时候也不必是说跟他一模一样的实现方式。
啊，等于说这边的实现是一些各种各样的这种字段。可能这边呢是一个内存的流，或者一个一个一个一个一个经过。比如说。
base 六十四编码之后的一个一个字符串啊，你用任何的一种编码方式把那边的状态都给他保存到这边都可以。
然后在这里边呢。
我们又提供了一定的接口啊，工程嘛供这个or later 来访问，下面这个就是member to 这个就是我们的备忘录。
好，那具体的做法呢，这里面示意性的代码其实看起来很简单啊，二十一行我创建一个啊这个我把。
我现有的这些状态塞进来啊，创建这样一个memento。
啊，这样一个备忘录。
呃，但是我也需要说一下，二十一行在实际的这个实现啊不同平台的实现过程中，这可能相当复杂。
对吧就是说你你里边字段的可能是很很多了。
这个时候往往用一些编码技术啊，所以我们说把它转成一些其他的存储格式格式，内存浏览啊呃。
呃，吃饭了等等啊。
啊，然后再返回这个对象。
等于就是把这句话其实就是拍照啊，当前状态，内存状态拍照，还有一个快照存出来。
然后呢，当然存出来之后呢，你在某些时候呢，我们先来看使用啊，一步步来开用。
存到备忘录对吧？就是我拿一个这个叫我们叫r d 内容，我们直接啊中文叫袁发起啊，我们这个研发器的创建出一个备忘录。
这是刚才用的这个行数啊。
穿起来这样一个备忘录的状态之后呢。
那我们这边。
啊，把它存储到这样一个备忘录的对象里。
啊，这个对象呢三十六行这个对象呢，它是。
哎。
一旦存储之后啊，他就应该稳定的，它不应该动的啊，就是这个memento 呢不应该有什么其他的乱七八糟的也接口啊。公公外界去更改。
对吧？
就外界不能更改这个map to。
好，那接着呢就是三十八行，就就是以后呢就就你可以去更改这个ratter，就研发器，就是与原始对象的这个状态呢，你可以随便去改它。
哎，就随着你的程序的这个这个运行，对吧？你可以更改这个对象的状态。
但是在某一点，比如说跑到四十行这里。
啊，用户做了某一个操作，比如说一个n do 的操作啊，或者一个什么样的一个需求，需要把我之前的那个点。
上存储的对象的状态呢拉回来。
啊，然后就是说恢复对吧？
那我这个our nature 呢？
就点set my mt。
再买了，它就是把我之前存的这个mm 图呢。
在什么在放到我这儿n 零那把我。
就已经改变过的状态呢，再赶回去。
就是具体做法在这这里面二二十四啊，我也需要说明一下二十五行，这里面是一个非常适宜性的代码啊，具体在实现的过程中。
比如说你可能用一些内存流的呃序列化的技术啊，或者是被是六十四的编码的技术啊啊具体去实现这个。
对。
没有。
呃，放鹿。其实呃整个设计思想啊就是这么一个一个方式啊，就是在大家再来看一下这句话。首先有一个前提是不破坏封装性，不分害谁的封装性。
or later 的封装性啊，就这个类物还是要实现我的信息隐藏的啊，不要破坏我的封装性。
捕获一个对象的状态。
这个就是补啊二十行提供的就是。
一种捕获对象状态啊。
那我可以把这个补充一下啊，要补货。
对象状态。
然后存储到备忘录。
并在该对象之外保存这个状态就是存储到网络，这样以以后就可以将对象恢复到原先保存的状态，这个就是恢复。
啊，四张。
这是。
这个模式这样说起来好像是。
有些朋友觉得哎挺简单的那种，是是吧？就是理解他罕见。
有一但是实现起来呢，具体实现呢可能。
不同的平台，包括你这个原发器这个对象呃实现的复杂度，对吧？你是哪些状态要保存，哪些状态不保存啊，你这个。
状态保存的量级是什么？
什么叫谅解啊？那你只保存一次。
啊，是保存一次还是在这个过程中陆陆续续要保持n 多个快内存快照。
你要保存n 多次，比如说五十四内存快照，那你就需要考虑性能的问题啊，你可能就是我刚才讲的，你要用一些序列化的技术啊。
用一些特殊的内存编码来技术呢实现对他们的一个高效的存储啊，这些具体实现起来可能啊在不同平台上都会有一些复杂度。
呃。
我们再来看一下这个具体的是呃这个类图。
这类图也是看起来很简单，对吧？那问头。
嗯。
啊，这是一个备忘录啊，然后这是一个our later。
它里面set mm to great，remember to. 
呃，可以呃这个create memento 的方式，就是说创建一个新的。
啊，嗯备忘录对象啊，然后呢这个呢啊set 太慢慢的就是把我里边的状态恢复啊恢复起来。
就是。
恢复成备忘录存储的那些状态。
啊，这边慢慢图呢就是在做这个事情。
这个呃car take care can take care。这是什么？其实就是使用备忘录，就是我们。
这样写这个没函数啊，其实就是啊can take her。他要做什么事情，还要利用这个不光对象来去实现啊保存和恢复的这样一个。
工作。
嗯。
备忘录的这个模式呢，我们说嗯他是一个小模式啊，或者甚至呃有些人呢在今天来讲。
啊，看他已经。
哎，哎。
认为他可能在今天这个模式有点过时，坦白来说是有点过时。就我们讲的这个设计模式里面啊，有一些模式呢。
确实随着时代的变化啊，有一些体现，有些过失。为什么大家想一下啊，别忘了设计模式这个。
这本书啊就是定义的二十三种设计模式是什么时候定义的？
想一想啊，九四年。
九四年这本书出来说出不来，对吧？
九四年各位是什么状态？
是吧九四年我我在上什么？我在上初中对吧？我想有些朋友可能九四年刚刚出生是吧？
或者刚刚上小学啊，所以九四年到今天这个信息时代发展的忒快了，对吧？
呃，所以以前呢在语言上，特别是以次加压语言以使毛套可以啊，对吧？九四年加二还没有呢啊。
还不要忘了啊，九九五年才有家啊，这个鱼。
所以这个时代发展很快啊，那当年的啊有一些设计模式确实是由于他的。
当时的内存环境，当时的语言条件导致啊这个有一些设计呃，有些模式呢呃需要用量用法。
方式来表达。但在今天的环境里边。
好，可能啊在实践上就显得非常非常的容易啊，我们来看一下呃。
呃，为什么讲这个比较容易的，就是呃咱们先把前面两句话说过啊，我们再说。张扬路的存储研发对象内部状态啊，在需要时。
恢复原发起的状态。这个就是我们刚才做的这个。
a mem to 模式的核心啊，它是信息隐藏。
他的实现技术，今天啊从今天来讲，其实呃已经变化的非常大啊。
呃，特别是我们有了很多序列化的技术。
啊，一些内存的啊这个这个呃编码的基础之后啊，往往咱们实现买卖图设计模式啊，已经不是那种以以前的面向对象的方式去实现。
啊，就是我说这个意思是什么呢？很少是今天的mmt 很少是这样做的啊，就是如果以二十三种设计模式，这个定义看起来啊它非常像说。
你这边定义一个字段这边定一个字段啊，比如这边再定一个字，字段，这边再定义一个什么样的字段，就是一句一映射塔。
这种做法太低效了，太低级了啊。就今天来看。
大家一般已经使用更高级的一些方式在做。
但这个思想没有变，思想是什么？就是你需要实现一个信息隐藏，这个是对谁的信息隐藏对or later 的信息。
对啊，就是r 英特尔需要向外界隐藏他的这个信息，内部的呃实现细节啊，从而保持其封装性。
但是同时又需要将状态保存到外界。
那么由于我们说由于现代语言啊运行是比如说像c hup java 七四家有也有很多序列化的库，对吧？都具有相当的这种对象序列化的一些支持。
因此呢，具体的实现方式上，往往可能跟二十三种设计模式当初定义的那种设计呃那种实现方式就不一样了。
啊，往往会采率啊效率更高的一些，并且容易正确实现。
啊，实际上这个背后实现是呃有一个很关键的地方啊，就是按照这两个对象。
弄出来啊这个状态捕获之后啊。
这两个实际上实现一个类似深拷贝的一个东西。
对吧，就是这个name to 对象要和这个原发器对象没有任何共享，而且又额能未来又能恢复过来。所以要实现一种深拷贝啊。
呃，这种内内存快照的方式。
那么深拷贝的内存快照方式，如果碰到一些复杂对象呢不太好实现啊。
啊，什么叫复杂对象？一个对象有，比如说里面没有指针，很简单，对吧？但是如果你里面有指针，里面再有再有几分。
啊，这是一一层一层的多级对象，这样的一个形成的一个类的hair rocket 啊，类层次结构对吧？这个时候呢。
他他这个是具体时间上升拷贝的时候不是不是太好实现啊，有的时候所以我们往往采用什么效率较高的一些啊这种。
序列化的方案来实现mmt 模式。
呃，当然走到序列化方式的时候，甚至有些朋友呢可能会认为这不就是一个朴简单的把对象状态保存的一个事嘛。
呃。
呃，犯得着给他套一个特别特别大的模式这样的一个帽子，然后来去解析它们。其实从这个角度来讲，也可以不必这么理解。
对吧，就是你不必说，哎，这是一个特别特别像我们墙模式啊，带奎屯的模式啊，或者是哦不走我观察者模式啊这么重的一模式。
这模式呢。
从这个角度来讲，它过时了啊，就是说你无非就是用一种序列化的方式在在实现这个问题啊呃。
但是这个就是大家有两个角度啊，我说两个角度，一个角度就是了解这个模式啊，number m to 模式它实现的是一个气息隐藏的前提的条件下来实现对。
对象状态一种保存，但具体实现的时候呢，今天的技术，今天语言和框架给我们提供的丰富的功能。
已经远远超出对吧？这个这个二十年前啊，九四年左右那个时候业界的水平。所以呢这个mmt 在有些人的眼里也都。
那个角度来讲是过时了啊，那么也就是我说实现的时候，你可以有非常丰富的想法和和记记技术来实现。
哎。
好，那我们这个模式呢就是大家呃用一种保留的方式来去理解和学习。他啊就是知道他。
是你具体去运用的时候呢，其实已经脱离了当年的这种实现给你的一种参考方案。其实可以跳出跳到更远的一种啊具有现代框架支持的是呃。
这种啊比如说序列化内存编码的基础上实现的话会更更方便性，性能也更高一些。
好，那my motto 模式我们就就讲到这里。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br></div></div><h2 id="_20-组合模式"><a href="#_20-组合模式" class="header-anchor">#</a> 20.组合模式</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>好，那我们开始我们composite 的组合设计模式的讲解。
呃，那组合模式呢和呃咱们后面谈的这个it at ure 迭代器和chain of responsibility 职责链啊。
都属于我们归到一个新的类别里面，叫数据结构模式。
我们为什么把这些模式归到数据结构模式里面呢？
原因是在我们的一些组件的内部墙上，有一些特定的数据结构。如果这个时候让外部去依赖这些特定的数据结构的话，会破坏这个组件的复用性。
呃，这个也是从咱们变化的角度来来理解的，对吧？这个时候如果将这些特定的数据结构，如果你能够封装在内部。
这y 呢提供一个一致的接口啊，实现与特定数据结构无关的访问。
就比较容易实现我们所要的复用性啊，我们首先来看composite 模式。
嗯，这个讲的意思跟我们刚才一样，对吧？如果你客户代码过多的依赖对象，容器内部的复杂的结构的话。
对象容器内部的实现结构的变化。
就是你依赖他，他便你就会导致你外边就跟着变啊，这样就不利于你的复用性、维护性、扩展性啊等等。
怎么解耦呢？我们康复的模式提出了一个。
一种解决方式，将对象组合成树形结构。
啊，注意以表示部分和整体的层次。
看不得的模式使得用户对于单个对象和组合对象的使用。
具有一致性。
所以这里的一致性。
一致性就是说。
我对待你三个对象和组合对象都是一样的，对待方式，一样的处理方式。在这就这就是一种富有性，对吧？好，我们来看一段呃也是代码来看。
一下，这是我们首先定义一个接口抽象接口。这个抽奖接口里面。
process 啊，当然可能还有其他函数，对吧？表示他这个上面的一些行为操作啊。
那我们定义了两种类型，一种类型我们是所谓组成一个树形结构，就是这个composite。
啊，他们在扯，那么它里边我们通过一个某一种数据结构，比如list。
构成了一个它的子节点啊，所以它的子节点是类型是什么？是component，对吧？是这里啊，那除了这个之外呢，大家再来看我们还有一个叶子节点。
这个叶子节点呢也继承次抗的。
啊，那他是。
呃，相当于另外一种。
一种树节点，一种叶子节点，对吧？他们都可以加到我们这个树节点底下。
大家看这个康不能测，所以。
这个list 里边大家看这个是个多态对象，对吧？就扛不动他他有可能是composite，有可能是list。
啊，所以就在能能体会到这个吧，就是十九行就表达了一个树形结构。
那这样一个树形结构呢，当然数据结构一般有数据结构的一些操作啊，比如说你往这个像这个添加。
节点是吧，然后移除子节点，这个添加的子节点呢，大家看component 就是同样的也既可能是又是一个树节点。
也可能是一个叶子节点，对吧？然后注意最关键的就是这里面的process 方方法。我们这里面是对父类的一个over right，对吧？
当我去o r n r 父类的这个啊虚函数的时候呢，我们会看到。
这里。
有两个步骤的处理。第一个步骤就是说我要处理当前节点。
比如说你要把当前节点的这个数值进行某种处理啊。
那么三十二行就是干这个事儿。
那如果我聊一下啊，就是这是第一步。
啊，这边呢是第二。
这第二步呢，你要处理叶子。
啊，先处于当前节点再处理叶子里。
而且叶子节点的时候，处理的方式，大家看我是使用的这样一个。
容器循环啊，在这里边呢啊e process 注意这个是一个虚函数的调用。
是吧？
这个这个这个序还是调用它最后实际上实现的是一个呃。
如果e 这里面取得在意，当前是一个炕鏂convent。
啊，是你这个composite。
啊，那么证明他又掉了了自身啊，那如果一取出来是一个list。
那么他就会。
调用到lift 的那个project，我们来看list the process。是这个。
啊。
那就是。
当然，如果是lift the process 执行的话，就就没有再再再循环下去了，对吧？大家能体会到这个这个实际上是内部有一个多态的。
递归的感觉是吧？
啊，就是e 依赖于e 的对象是什么？如果是树节点e 就继续往下掉，对吧？就是自己都要自己啊，如果是呃也不是自己道第几次自己啊，只是说调用另外一个树节点的。
方法，如果e 是叶子节点leaf 的话，他就盗用类的。
呃，是节点的叶叶子节点的一个一个process 方法。
就是注意这里边啊，我们说实际上是背后有一个。
这是一个多态的调用。
嗯。
可能是树节点，可能是叶子。
呃，这样就完成了是吧，针对啊这个抗磨zit 这个树节点底下的所有的处理，对吧？我如果标的更详细一点啊，这个是一个什么？
树。
谢谢。
然后这边呢标的是一个。
叶子节点。
啊，一个树节点，一个叶子。
好，那有了这个调用之后呢，这个这个实现之后呢，我们再看我们假如说有一个啊处理程序，这就是客户程序啊。
五十二行是一个客户程序。
这个客户程序我去处理的时候呢，我就接受component。
啊，作为我的一个参数，然后进来之后呢啊我可能做一个这样的处理量处理。然后我调用比如说c 点process。
好，注意，这个也是一个多态的对象，对吧？它是可以引用类型的引用对象啊，那么这是一个多态的调用。
呃，当前比如说如果是特殊节点，如果是一个根节点，don't process 的时候，他就是怎么呃先从这下来。
啊，下来之后呢要去看查询它里面的所有元素。
所有元素挨个掉，每一个元素，又看你是不是你是个树节点还是叶子，是吧，分别的。
而如果我们看一下，比如说这是一个适应性的演示，使用上面的呃类设计的一个代码。比如我们首先构建了一个树。
这是一个根节点，然后呢这是树节点。吹。note 一training，the rat note 三乘四，然后啊泪。
这类f e 类f 二。
啊，然后呢我们在这里。
把这个人赶过来。
再数一。
af 二。好，那我们在这个根节点上加先加一个树节点，对吧？最多的一吹到这一底下要加一个note 二。
选择的二底下又加了一个类负一啊吧。然后呢在这边呢根节点那边，另外一个节点上加了一个note 三衬衫下摆一加一个变成四。
选择四底下又加了一个列弗二，好，构成了这样一个数啊啊那这个数负啊。
真正去处理他的时候，比如说我把它丢给process，发现这个是不是。
针对你这个process，那都是一种非常统一的处理方式啊。
当然了，如果你这个process 你也可以去处理。
比如说内服二啊，那它的处理的时候也是一样。
甚至于你在这里面process。
啊，这个吹。
有的三。
嗯。
别说对，那也是一样，这就是具有一致性的意思。七十八行到八十行针对，你不管是跟节点还是树节点，而叶子节点我的处理都是一样的。
啊。
但是要不用这个，假如啊不用这个composter 的模式，它会带来什么问题啊？
比如说你这里边。
和做这个。
啊，不做三十四行到三十六行这段代码。
那大家想这个地方的处理，你就要分别处理了，对吧？就是如果这个类型是。
lift 节点应该怎么处理？
如果这个类型是啊这个composite 这个树节点你应该怎么处理，而且。
这个时候处理的时候，你应该你就要把它内部的数据结构刨出来。
对吧，针对性的来解决。而这句话呢。
这是三十四号到三十七号，实际上是把内部的数据结构的访问封装进去了。
啊。
再有没有理解这个实际上如果你看看懂这个代码，其实很容易理解，这就是一个典型的树结构的一个啊。
父亲的数据结构的一个处理方式。
啊，只不过是我们在访问的时候呢。
我们实际上是用一种多态的方式把这个树形结构的访问栽在了这个封装在了这个树形结构的内部，而不是要把这个数据结构暴露给。
外景。
好，如果我们这时候回到这个p p t 再来看一下啊。
体会一下这句话，将对象组合成树形结构。
这是composite 模式的一个非常呃独特的数据结构方面的一个特点啊，就是他一看就是个树形结构，对吧？以表示。
部分和整体的一个层次结构。
看不见的模式使得用户对于单个对象和组合对象的使用具有一致性。
啊，刚才一致性我刚才已经讲那一段代码，对吧？
就是。
再切换了一下。
哪里就行，这里对吧？这个地方就处理就是具有一致性。
不管你是树节点还是叶子，我都是这样处理的。
好，那我们来看一下这个啊u f 的这个不是啊类图的示意图。
要看看不能撤，我需要说明一下这个add remove。大家看啊a 的remove get child。
其实呢这个这个是有争议的啊，就是放在这三个函数是放在component 父类里面，还是放在这个卡plate 这个紫薇里。
呃。
都有不完善的地方。他们还说，如果放到父类里面，其实对于这个类负节点呢就很尴尬。大家想内部节点面临的。
就是说你既然是子节点了，而是叶子节点啊，那你还可以爱的嘛，可以remove 吗？不可以啊，不对，当然有些朋友可能会说那个艾特remove 让他实现成空的。
呃，就是大花果号里面什么都不写是吧？
二十四户也不舒服，对吧？因为他毕竟是一个类似节点。
所以有的实现呢，像我们这里实现也采取了一种方法，就是压根就不给他提供爱的人。
原木。换句话说，我们在computer 的这个类的层次里边不给他提供i remove，而是在composite 这个层次里面呢提供。
啊，当然这个也稍稍有那么一点点。
我不太不太美的地方，对吧？就是什么？就是你将来要添加的时候，你就需要分辨类型了，是吧？因为内属不能内服，没有添加能力。
而只有component 有添加，composes 有添加的。
对吧，有爱的和人物，所以你这个时候就要又要去判断类型了。
但这个地方确实是有一点尴尬的，但但确实没有特别完美的解决方案。就像我刚才说的，如果你在那个component 这个腹肋啊，就是这个抽象基类里面去写这个两个函数的话。
你的利斧是非常尴尬的。
阮丽芙，你实现成空烘。实际上你在欺骗人啊，对吧？人家加了一个东西，你你你花鼓号里面啥也不干，你这不就骗人嘛。当然有些朋友会说，那思路一个exception 呢。
人一个异常。
其实也不合适啊，行行啊，就是父类父类有俩虚函数的放好了，然后子类实现这个虚函数的时候呢，直接扔异常，这个其实违背了什么？
is a 这个关系准则，对吧？
就是我我指的是一个负累。那你父类定义的接口呢，我之类应该是可以实现的啊，那现在你你你有你有扔异常，就表明你不支持父类的接口。
其实又违背了此类呃支付类的关系。
呃，都有，不是那么那么完完美的地方啊。但是相对来讲，我觉得我个人理解啊就是爱的remove 放在下面更合适。
事情。
啊，就是在考bonner 的这个层次上，不要放爱的人物，否则在咱们目前就c 家园这个机制来讲，这个类服很很尴尬。
呃，当然认为那不是重点，重点在哪里呢？在这里大家看啊再测里operation。
啊，operation. 
啊，就是他里边啊就是composite the operation，它里边其实这个这个媒体啊应该是处理当前节点的。
接着又要处理他的所有子节点。
啊，所有子节点的方式就是实现多态的递归调用啊。
对吧，注意这个里边背后有那么一个多态递归调用啊。
嗯。
当然这幅图呢，我们说实际上哎只是表达了一个非常啊。
呃，从粗略的呃针对咱们这样一个compute 的设计与具体在做的过程中呢，可能也有很多很多其他的一些处理呃啊。
抽象逻辑，但是最核心这里面最最最主要的表达还是说用一种多态的等方式，针对树形结构和叶子节点进行一个统一的处理。
好，我们做一个针对这个模式，做一个总结啊。
首先我说扛不住的模式采用树形结构来实现普遍存在的对象容器。
从而将注意它是将一对多的关系转化为一对一的关系。
这句话怎么理解？
啊，我来切切回来啊。
就是说如果你在这里不这么做。
对吧就是我们说把这段代码假如给他藏起来。
那么。
咱们在这个地方。
就需要实现什么？
啊，一会儿是一对一，一会儿是一对多，对吧？这你要去判断当前的component。
只是内付呢还是要靠谱，呃，还是个还是还是这个composite ate 呢？也就是一次节点呢，还是树节点的。如果是树节点要取出它的里面子元素，要继续处理。
那就是一对多的关系，如果是叶子级的，你就针对叶子晶啊一呃处理，那是一对一的关系，对吧？那现在呢那那当然很麻烦，而且暴露内部的数据结构，对吧？
现在呢我们实现了这样一个多态的递归调用之后。
那对于这个地方就是这就是一对一的关系啊。我刚才讲的这句话就是这个意思啊，就是将一对多的关系转化为。
一对一的关系，从而使得客户代码可以什么。
一致的。
处理对象和容器无需关心处理的是单个对象还是组合的容对呃，容器对象是吧？
将客户代码与复杂对象容器结构解耦是compute 的这个核心事情就是我外部程序根本不用关心你内部是啥。
啊，内部是树还是什么叶子，我就处理你的时候是统一的处理。
客户代码将于纯粹的抽象接口发生依赖。
对吧就是说咱们刚才那个invoke 接受的参数是什么？是抗通ent 这个虚基类是吧？积累。
嗯。
呃，不应该叫虚机的啊，就叫积累啊，就是纯虚函数，纯虚基类，纯虚函数生成的积累。
啊，超应该是抽象积累的，反正你依赖，从而什么来应对变化。
呃，当然具体实现还有一些细节啊，卡布叻的模式在具体实现的时候呢，这个副对象和子对象的这样一个啊，你是不是能够从父对象找他指的巷子，就象在找到付对象有没有反向追溯的这个能力。
啊啊。
如果付对象有频繁的电力需求呢，这个是可以使用一些缓存的技巧来改善这个这个便利的效率啊，这个都是其实是算法。
处的反射法层面的一些一些具体的技巧，但它不是咱们computer 模式的核心啊，卡顿这个模式的核心是通过多态的这样一种递归调用。
对，来解耦了。就当然前提是你要有一个树形结构来表达你这个结构啊结偶了内部和外部之间的一个依赖关系。
好，那我们composite 设计模式就讲到这里。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br><span class="line-number">177</span><br><span class="line-number">178</span><br><span class="line-number">179</span><br><span class="line-number">180</span><br><span class="line-number">181</span><br><span class="line-number">182</span><br><span class="line-number">183</span><br><span class="line-number">184</span><br><span class="line-number">185</span><br><span class="line-number">186</span><br><span class="line-number">187</span><br><span class="line-number">188</span><br><span class="line-number">189</span><br></div></div><h2 id="_21-迭代器"><a href="#_21-迭代器" class="header-anchor">#</a> 21.迭代器</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>嗯。
好，那我们开始我们自己家设计模式，litterature 迭代器模式。
呃，谁的气也是属于咱们一个数据结构模式啊，跟我们composite 模式啊类似，我们都把它归到数据结构里。
我们来看它解决的是一个什么样的一个问题。首先在软件构建过程中啊，集合对象内部结构常常变化各异，对吧？你可能。
比如说vector 是吧，你啊list 啊、链表啊或者内部使用营数啊等等各种各样的结构啊，来去实现一个集合。
但对于呃这些集合对象呢，我们希望在有些情况下暴露他内部结构的同时呢，可以让外部客户代码呢能够透明的来去。
访问其中包含的元素。
啊，同时这种透明的便利也为同一种算法在多种集合上、对象上啊进行操作提供了可能。
啊，显然就是我不关心你内部的实现结构。我一种算法可以应用到比如说一个树形的结构里面，也可以应用到一个。
啊，结合的结构里面也可以应用到一个比如说链表的一个结构里面，或者一个堆的结构里面，或者一个这样的结构里面。
唉，那不管你的内部实现是什么样子啊。
呃。
那我们首先来看一下j o f 定义的这个迭代器是怎么来做的，提供一种方法，顺序访问一个聚合对象，就是我们讲的集合中的各个元素。
而又不暴露。
大家注意这个不暴露这个词啊。
啊，在咱们设计模式里面，经常会有这样一些词啊，大家要能够参透它背后的一个含义，不暴露就是什么就是隔离变化。
这是让外界得以稳定。
对象内部的表示。
嗯。
gif 最早提出是用面向对象的方式来实现迭代器的。
但是在在讲这个面向这样这个这个模式之前呢，我我还是需要啊特别重点来说明一下这种方式啊。在c 加加今天来讲已经过时了。
啊，为什么过时了呢？
因为啊学过咱们sql 和泛型编程的朋友都知道。
在我们泛型编程里面，有著名的迭代器，对吧？它的思想和我们今天讲的这个迭代器的思想是一样的，都是通过什么？
一个一种接口的方式来去什么隔离算法和容器之间的一个一个变化。
啊。
但是呢gif 当初定义的是什么？是用一个面呃就是面向对象的方式来定义的。
啊，我们先来看一下gif 定义的代码。
面向对象的方式在这里。
大家看这个这个aerator 呢？
其实就是我对着图之间来看啊，就在这里是吧？大家看啊。first next is one, the current. 
就是所谓提供你第一个元素。
然后next 就是让你的元素往下走，对吧？啊，下一个元素啊is down one 啊，就是当就就就就是大头了，对吧？然后current 就娶你当前的元素。
当然有些设计呢会把这个什么啊。第八个这个next are a 呃就是第六个这个next 和第八个这个current 和两个接口合一合二为一。
啊，就是有些内裤里面会这么做啊。
嗯，那么没关系的，那那都是细节对吧？我们再来，然后再来看有一个collection，有这个collection 呢它会返回一个迭代器。
get it ratter 啊，返回这个迭代器呢，就是属于我针对我这个结合的爱情。当然这个一般是针对他的这个集合，要设计一个。
某一种特定的集合迭代器类型。your collection, it rat or 好。然后在这里呢去。
继承这个类啊，it erat 这样一个i。
我们就是在这里一个抽象类是吧？然后呢在这里边。
实现他的first 第一个元素，next x 元素，a x 单元sit down one。啊这样一个判断，然后current。
呃，当然一般啊在这里面实现的时候，你需要把这个集合传进来，然后你不穿这个集合，你不知道这个情况内部信息啊，那这两个的泪也很密切的啊，关系很密切。collection it rat or her collection. 
呃，这个。
collection a american collection. 就相当于咱们这里。
对，相当于这里my collect。呃，他有一个什么十八行，这里啊就是create 或者get it at，or 它返回一个literature。
啊，就是返回这样一个迭代器，然后具体使用的时候呢，my collection set 一个int 啊，就是这这是一个我用一个泛型啊，就是一个模板元素而已啊，模板类型。
啊，这不是不是重点啊，我们的重点是就给他起。
然后get it later。拿到它之后啊，我就可以去便利它。
啊，first the next 啊，然后判断它是否一直down。然后在这里面呢去对这个元素进行某种算法层面的处理。
呃，这就是当初g o f 定义的以面向对象方式定义的迭代器。
啊，这是到现在在我们当我们说到面向对象的时候，什么特征啊，多态是面向这样的核心特征就是这里大家看。
四个虚函数是吧？
然后在这里面去over yy 的他们了。
然后在这里调用的时候，使用的是一个多态机制。
这个地方调用的是多态，这个地方是多胎，这个地方也是多看这地方也是多台，这就是这就是面向对象。
哎，映射到咱们刚才在这个类图里。
啊，但是我在这里需要特别强调的就是说这种设计模式在c 加加这个。
这这个语言里边这个已经过时了。
呃，为什么讲他过时了呢？
就因为泛型编程和这个s tl 库的啊，在大概在九八年出来之后呢，大家一对比发现哇这个面向对象实验的方式有很多缺点啊。
具体来说，他最核心的缺点是什么？就铺在面向对象上。
啊，就是这个面向对象的方式，大家看这里面都是虚函数调用，对吧？
虚函数调用是有性能成分的。
就是具体就是要绕一个什么虚函数的啊表指针啊，然后找到你那个函数地址，然后去调用。就是我们要经过二次。
他在呃指针的一个间接运算，这个间接运算呢每次都这么干是吧？你你你一次成本显不着，对吧？但是。
大家看这是多少次啊，这是一个循环啊。
你这个这个这个集合里面有十万个元素的话，那这个循环就进行十万次。
使每一次可能差一点，但是十万次的差就很多了，对不对？所以我们说这里。
啊，大家要注意这样一个一个一个特点。
first is one next partner. 全是虚函数调用，它全都有性能成本。
呃，那么cnr 在泛型编程九八年左右啊，这个标准化之后的泛型编程。
啊，使用的是什么？就它里边的迭代器，大家知道它里面。
第一呢，它的迭代器是使用模板来描述的。
啊，而模板呢在是一种我们我们说实际上模板也是一种多肽技术。
也是一种表态，但他实现的多态是什么？是边a 意识多态？
啊，就是编译器在编译的时候会变稀，这个具体是调用哪个代码，对吧？但是呢。
咱们这个虚函数呢是叫做什么运行时多态。
运行时多态性能要低于编译使用的。因为因为就是说那编译时已经把这个工作做了，对吧？就运行时就直接掉那段代码。
就不需要再去计算它的函数地址了。
啊。
因此首先我们说。
泛型编程就以sql v 标准的这一套泛型编程的方式呢，它使用的是基于模板的这样一个多态的迭代器。
他的性能要高于咱们基于虚函数面向对象的方式的这种迭代器啊。
而且第二个大家知道了解泛型编程的朋友要知道。
翻译编制里面的这个迭代起来有很多种迭代器啊，这迭代器其实就是它的接口呢还发展出来的更多的可能性。
啊。
呃，具体来讲就是咱们这种迭代器，大家看啊这种迭代器只知是什么。
往前走是吧，不支持往回走，他知他缺点啊，他只能next x 不能什么back，对吧？and the back. 
但是我们知道在c d 阿里泛型编程里面，那个迭代器啊，它可以就加加往前走减减往后。
走啊，甚至他可以加n 哎，就往前走n 步啊，减n 往前往后走n 步。
这些当然有些朋友说，那通过渲染树，通过这个，其实你想实现也可以啊，可不可以可以，但是。
真的成本很高啊，而且到目前来讲，我没见过有有第三方内部这么干的啊，就用限速的方式来实现多种迭代器。
所谓多重迭代器，在咱们s t 二h 什么。
前项点呃制度前向迭代器，然后就是一个是input 的迭代器output。the 二七for w 的迭代器啊嗯双向迭代器，对吧？
有什么随机迭代器就五种叠在一起，在咱们这里只实现了一种。
但是那个那个灵活性在哪里啊？那个灵活性其实就是模板它是基于什么，皆是基于隐式约束的。所以呢他可以用像佳佳操作服务减减操作符啊等等这些。
作为他的接口描述。
就是模板的接口描述啊。
是吧就是你支持佳佳，就说明你这去加压这样一个一个操作。那家家就是对你接口的一个描述。而我们运用面向对象的话，只有虚函数这一种手段。
啊，所以在这里在就具体到这个场景，虚函数还真的是不太好啊。
呃，而且事实也证明啊事实也证明，就是说工业界对吧，我们整个这个系统系统软件层面，大家都发现有了泛型编程的迭代器。
让大家再也不愿意用什么面向对象的迭代器了。
所以这是有这样一个大背景要告诉大家。
呃，但是呢这种迭代器的设计思路在其他语言里边。
比如说java c 十二。
php 啊啊swift 啊很多很多语言里边。
得到了是吗？极大的应用就是还是基于什么运行时的多态机制。
啊。
简单来说，其他的语言他就不支持编译时的这种模板机制。
就鞭尸的多态啊，其他语言啊很少很少像c 家这样支持。
所以在七大家学了这个设计模式呢。
你去看java 的内裤，看c shup 的内裤，对吧？等等你一下就看的非常清楚啊，他的设计就是这样式，但在c gr 内裤里面，你可能很今天来讲啊，以前可能还能找到。
对吧，就在今天来讲，你很难找在c 家的这个工业级的这个软件里面找到这种迭代器的实现方式了啊。
对，这也是我们上节课前面曾经讲过啊，就是随着技术的发展啊，有些迭代，有有些设计模式它会过时，他的实现它的思想不会过时。
啊，比如说这个思想不会过时，对吧？其实我们说范型编程里面迭代器的思想也是打这儿来的啊，通过什么一个迭代器来隔离。
隔离算法和什么和容器，对吧？这就是迭代器的核心思想。但是呢实现的机器技术方面已经有了。
啊。
呃，所以这个模式大家学的时候要要警惕啊，就是要要要结合时代的这样一个背景。
好，最后做一个简单的总结，就是这个有迭代呢迭代器有两个层面的需要。大家理解。第一个是就是迭代抽象，就访问一个聚合对象的内容，而无需暴露。他内部表示。
对吧，就是我我不需要关心你这个内部是就是我说的你是你是链表实现呢还是竖写实现呢？
还是一些这个呃堆实现呢暂时线呢都都无所谓，对吧？呃，这是这就叫所谓的迭代抽象。
第二个呢叫迭代多肽，就是为便利不同的集合结构提议提供一个统一的接口，从而支持同样的算法在不同的集合结构上进行操作。
啊，那这两种方式不管是针对咱们使用c 家的模板的多态啊，就是静态多态。编译时多态的方式来做啊，也是适用的。这个思想都是在。
啊，有一个小的地方需要在实现迭代器，就是要考虑一下就是迭代器的健壮性的考量啊，就是便利这个迭代器所在的集和结构啊。
就如果你更改的话啊，电力的时候你如果有有更改的话，可能会导致问题呃很多迭代去要求是只读的。
啊，就是迭代器你本身啊不能。
去去去改来改去的，对吧？但是如果你这个迭代器是一个指针，对吧？指向内容啊，那你可以改，这是没有问题的，对吧？但是迭代器。
自身像很多迭代，其自身他要求是一个制度的问题。
好，那这个迭代器这个模式也是一个我们说由于啊时代变化啊，他导致他有一些过时的这种情况。
啊，所以大家嗯简单了解一下这样的一个设计方式。但是你真正应用起来的气的时候，对不起，还是要回到什么最佳泛型编程主导的。
以模板多态为主导的这种迭代器上。
好，这个模式我们今天就讲到这里。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br></div></div><h2 id="_22-职责链"><a href="#_22-职责链" class="header-anchor">#</a> 22.职责链</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>好，那我们开始我们ccr 设计模式啊，职责链这一讲。
橘子练呢跟咱们前面讲的组合啊，迭代器这些模式都属于咱们讲的数据结构模式，就是他体现出一定的啊特定的这个数据结构的特征。
嗯，我来看一下职责链解决问题的场景啊，是在软件构建过程中，我们说一个请求呢可能会被多个对象处理。
但是呢每个请求在运行时。
只能接受啊呃只能有一个接收者就处理者。
如果你显示指定的话，有的时候场景是不太可能啊，有的场景呢是说你显示指定或带来很高度的这个发送者和接受的剪耦合。
嗯，我们又如何？
解决这个问题啊，将就是说是请求的发送者不需要指定具体接收者啊，让运行时。然后这个事情运行时来自动的根据自己的逻辑来判断。
呃，这个问题呢我举一个例子啊就是。
你说我们嗯像在windows 这个w p f 啊里边，包括在像这个麦克上的，像l o s 呃这个o s。
或者是l o s 系统里面。
都会有一些界面的处理逻辑，不是这样子的。就比如说顶级的是一个呃呃窗口window。
接下来呢比如说有一些嗯。
呃，这个table 啊，然后再往下呢又有一些比如类似的啊，有一些这个这个嗯text box 啊等等，就是说一层一层对象。
那么当你比如说你鼠标点击或者拖拽，或者是一些其他的触控的操作啊，那可那这个时候呢这个事件呢。
要是会沿着这个对象的这个层级链条，一层层往上传播，就是你第一集没有处理，他没有处理这个世界的话，这个事情就继续往下一级传播。
那这个场景呢其实就是我们这个职责链的其中的一种可能的场景。
当然在更更多范围内，还有一些其他的可能性啊。
呃，我们来看一下这个模式的定义，使多个对象都有机会处理请求，从而避免请求的发送者和接收者之间的耦合关系。
具体的做法是什么？将这些对象形成一个链，这个链具体其实就是一个链表。
呃，这也是我们之所以称它为数据结构模式的原因啊，它形成了一个链表啊，就这样一个结果。然后沿着这条链来传递请求。
直到有一个对象处理。
呃，好，那我们来先来看对照一段代码来看一下啊，这里是一个训性的代码，这是定义一个枚举类型。我们可以。
不用太关心这个枚举啊，我们先往下来看。
呃，这里边呢有一个request 的对象，这是一个具体的负责请求啊这样一个。
携带的一些请求信息。
然后呢，这个具体的处理者或者讲叫接收者啊，就在我们这里。
大家看这关键的是这一点啊。
看二十五行二十五行这个指针呢就行，只指向自身，对吧？
而且他是作为一个鸡肋存在的那那其实这是一个多态的指针啊，这个多态指针指向自身就形成了一个多态的一个链表。
啊。
呃，这个链表呢里边大家来看，接着就有一个列表的处理逻辑。就。send the request to the next handler. 
他的逻辑是，如果我这个链表下一个节点不空。
我就把我这个请求让下一个节点继续处理。
好，接着呢我们又呃弄了两个区函数程序函数，它们分别的含义，就是说一个是来判断这个请求能不能处理。
啊，这个其实就是在运行时来判断啊这个请求事实。我当前这个憨掉了是不是能处理你这个请求。
呃，第二个逻辑呢就是具体的去处理这个请求啊，就是请求的处理的具体的业务逻辑啊。然后在最初始的初始化的时候呢，我们再把这个。
链表的指针呢制成空指针。
然后呢，再有一个就是set next change 啊，就在我需要构成一个链表的时候呢，我就用这样一个方法来建立一个链表。
好，然后再来看三十九行，三十九行像是呃整体的一个处理逻辑啊，这个就是。
嗯，我们刚才讲这个最逻辑，大家来看他首先做一个判断。
af can handle request. 就如果我当前的这个对象能够处理这个请求的话，我就去处理。他就是四十二号。
那反之呢，如果我处理不了怎么办呢？send the request to the next handler. 
其实就是调用那个叫这个是吧，这个方法。
当然了，其实你这个方法啊实际上也可以呢。
把它呃这个直接写写在这里面啊，也也可以啊，这无所谓。
但总之就是这里面清晰的看这段代码，四十一行到四十层清晰的指出了这个职责链里面的一个处理逻辑，就是我当前链表节点不能处理，我就交给下一个链表。
节点来处理啊。
好，那这个鸡肋其实积累已经把主要的这个逻辑写完了。写完之后呢，我们就去去去实现具体一个一个的handler。比如说这。
这个具体还那就是。
啊，over right 的这两个血函数啊，一个渲染树kh and request。
呃，这个呢当然在具体实现这个过程当中，有各种判断方式啊，只就是强调它是一种运行时来判断。
啊，那我们这里是用了一个所谓的get type 是吧？get request the tape. 
就是看看你这个请求对象的类型是什么，然后呢，是不是和我这个匹配。比如我当前这个h 德勒伊就是要处理吗？
这个请求类型是这个枚举类型的啊。re request header 零一的这种情况，那我们就判断是否是否等于这个枚举类型。如果等我就返回处要吧，否则false。
那么。
process request 啊，这个方法呢在这里面就只是一个具体的处理逻辑了啊。那么我们就是在命令行打一行字啊，就是说哎我这个汉德勒伊正在。
处理你这个具具体的一个请求。
好，然后再有汉德拉二啊。
也是这样子啊就是。
一样逻辑对吧？就是也是在这里面去判断。当然这个时候的运行时的判断，我是根据另外一个枚举类型。
看到了三啊另外一个枚举类型，其他的大家都大同小异啊。好，那么我们来构建，首先构建出啊。
三个汉代了。
当然这三个handler 其实有的时候呢，如果你也可以有一些比如说在构造器呢直接传递他的nex chain 也可以是吧？
其实只不过我们这里没有用这种方式实现啊。
啊，而是用一个方法来实现。
呃，在哪里啊，在在这里对吧？三十九号你其实也可以传参数啊。
好，我们一个方法来。总之大家看现在构成了一个链表，h 一里面有一个节点指向h 二，h 二，有一个节点指向h 三，对吧？就构成了这样一个列表。
好，那建立这个列表之后呢。
呃。
其实然后我们再看九十二行，就拿这个request 的对象。这个request 对象我其实就是告诉我，嗯，我将来希望。
哪哪一个对象来处理我？
呃，就是在这个枚举类型这表达的。但是我也说过了，这里为为了只是为了我们演示的必要性，我们写了相当简单，只是用一个枚举类型判断。
啊，在具体这个实现过程中啊。
嗯，就这个运行是判断往往没那么简单啊，可能是一个很很特定的一种业务逻辑来去判断他们。
好，那这样的话就是说丢给他，就是把这个请求对象呢丢给这个。
h 一我就先从这个链表的最开始啊，就这样我们说最最最最最最开始的第一个节点开始交给他。
然后。
要看这个请求是不是就会沿着这个列表不往后传播，传递的过程中，遇到哪个对象能处理他啊，就处理他。
离不了，继续往下传递。
啊，这就是职责链的这样一个整体的逻辑啊。
呃，就是我们刚才说的具体实现的时候呢，有很多地方呢有很多灵活性啊。三但是我们这个代码里面刻画的。
最核心的。
一个一个业务逻辑，就是刚才这句话。
啊，我们我们用这个画笔把它勾勾出来啊。
就是组成一个链一条链。这个链具体来讲就是咱们的一个单链表。
啊，单向的一个列表沿着链来传递请求。
啊，这是职责链的形成的一个一个。
固定的一个一种结构形式。
嗯。
当然职责链啊这个模式呢。
谈到今天呢，就是说有有一些人甚至在眼里觉得这不是模式。
对吧这也是这个，因为今天呢就是数据结构已经发展非常的呃。
非常成熟了。在有些人眼里呢。
哎，就觉得哎这就是一种数据结构的表表达方式而已啊。但是在在早期啊，大家一定要理解，就是我们设计模式这个思想的提出呢。
是在什么九四年？
啊，就这本书呢这边记很经典的书呢，是在九十多年前写就的九四年当时就是我讲的有一些固有一些观念。
在就不是那么成熟啊，所以大家会遇到这样的问题，也会把它列为摄影。
但今天来看呢，有些人不一定把非要把这个当做一种非常特定的模式，甚至就是制作啊他他就是一种数据结构，对吧？
来构成一个一个一个处理模型而异。
嗯，那就自恋呢。
我们来看一下这个这个类图啊，也其实也很简单啊，其实他的核心呢大家来看这里。
还是希望这个部分是稳定的，是吧？
呃。
请求。
的发送者和请求的接收者在这个部分是稳定下来的。
然后具体底下的这些处理者。
啊。
我们用还是用这个蓝色的笔来画下来了，就是你是变化的，对吧？
就是我可以有各种各样的呃这个这个具体的就是比如我在一个窗口的层级系统里边，我可以有各种各样的对象。
啊，呃可能会添加五个，可能就会添加八个，那个都可以。
但是呢这个逻辑是不变的，这个逻辑是写在哪里？写在红色的部分呢，对吧？就是让他永远暗恋传播。
嗯。
对，那么我们简单来总结一下啊就是。
首先呢我们必须承认直刺链这个模式呢在今天的整个软件框架里面应用的确实不多。
啊，甚至有的时候就是我说的你你已经用一种列表逻辑在处理你的程序了。但是呢你可能并不意识到它是一个职责链的模式，这也这并不重要。
呃，他不像我们前面讲的有些模式是非常的流行啊，对于设计的这个。
呃，这个框架的应用非常是一种高频模式。我说这这个模式其实也是跟咱们这个像有些呃之前提到的有些模式一样，比如说mmt。
对吧，像白猫头模式也是由于有了序列化框架，成熟的序列化框架之后，文文图模式都不成为一个特别特别大家呃认知流行的一个模式。
自恋是这样，他他很少用用的很少啊。
对，那么这是他的一个前提啊，然后我们再。
做一个简单总结，就首先说侄子模式，它的应用场合在于什么？一个请求可能有多个接收者，但最后真正的接收者只有一个。这个时候呢，请求的发送者和接收者的耦合。
那可能会出现变化脆弱的症状。
所谓变化脆弱，其实就是说。
大家想刚才那个如果你不用链表，不用形成一个列表来解决你你具体会怎么解决呢？
你是不是要把这一大堆塞在一起啊，然后当然有的人会把他们塞到一个数据结构里面啊，自己在在在。
从头到尾的来去便利这个数据结构自己来处理啊，那这个就不太啊，就是说好的原因就是就是说耦合高度融合。
嗯，之子类目的是将这个两者解耦啊，从而来更好的应对变化。
啊，也就是说我请求者，我只关心我就把这个球踢给第一个处理者。这以后这个怎么办？第一个处理者会帮我处理好。
应用了职责链模式后呢，这个对象的职责分派啊，其实核心是一个我们叫做responsibility 的一个dispatch。
啊，就是责任的一个分发将更具有灵活性。
而且最重要的是什么？
啊，看一下，我把这个笔还是。
改成红色的吧。
啊。
最重要的是这个。
具有运行时动态的这个特征。
这运行时来什么来辨析？
哪一个处理者可以处理这个请求？
啊。
如果请求传递到职责链的这个末端呢没得到处理啊，应该啊应该有一个合理的缺省机制。
这个这个在有些机制应用里面，实际上就是说什么都不做，对吧？
但是这个不是请求的对象的责任，这个是接收者的责任啊，你接受者到就是传到最后还是没有任何一个对象可以处理这个东西。
啊，这个时候应该应该怎么处理？有一个缺省机制。
好，那我们来稍微回顾一下嗯，我们三个。
这三个模式啊。compositor chain of responsibility. 
呃，就是我们说的，首先这三个模式为什么把它归到数据结构模式，是因为这三个模式的特征非常明显，分别是什么？第一个composite 是由构成一个树形结构。
第二个it rat，or 呢它是一个迭代器啊，它典型的是在处理容器的这个内部的数据结构和外部的依赖关系的这个过程。
啊，主要是一种便利啊需求。呃，嗯第三个呢职责链它构成了一个链表，一个单链表。
啊，结构。
呃，我我我把这三个归到数据结构模式，是希望大家从呃认知上啊能够很快的去辨析出来哦啊。
还有一种很强的共性的特征啊。
但是坦白来说，这三个模式呢。
嗯，我们说it aerator 和职责链呢就是。
过时了，在当前的这个编编译一下啊，就是用的不是特别多，conversion 的模式还可以啊，高温的模式呢。
呃，尤其是构成一些树形结构的这个这个里边呢还是有一些经常会会用到的。
好，这就是这一这三个模式的在在这个呃我们简单说一下他的一个应用的呃进度和肠镜。
好，那我们今天职责链的模式呢就谈到这里。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br></div></div><h2 id="_23-命令模式"><a href="#_23-命令模式" class="header-anchor">#</a> 23.命令模式</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>嗯好，那我们开始我们四家设计模式，command命令模式这一讲。
那我们把命令模式和后面要讲到这个vision模式呢归为我们一个新的类别，叫做行为变化模式。
呃我们来解释一下啊，行为变化主要是我们指的是在软件构建过程中啊，这个组件行为的变化经常导致组件本身剧烈的变化。
其实大家想啊，这个行为呢一般我们说是一段代码，对吧？
这个代码和对象之间的绑定关系是极其紧密的，实际上它是一个天然的编译室绑定，对不对？
就是如果了解的话，大家知道你一个类，对吧？
写完。
成员函数之后，那你这些成员函数分为两类啊啊这个一类是虚函数，也是非虚的或者静态的函数啊非虚的或者静态的这种。
呃函数呢它实际上是这个地址呢直接什么以编译室绑定的方式绑定在一起，然后序函数呢是以命令呃运行式绑定的，通过序函数表指针绑定在一起，但这些绑定呢实际上是非常非常简偶合的一个。
那行为变化模式呢，将组件的行为和组件本身的进行结构，从而支持组件行为的变化。
这个当然变化有多种层面的变化啊，我们待会儿看两个模式，实现两者相吻合。
好，我们来首先来看一下谈判的模式，解决的问题是场景。
呃在我们软件构建过程中啊，行为的请求者和行为的实现者通常会呈现一。
用金偶合啊，但在某些场合，比如我们需要对行为进行记录啊，撤销了就是维度安度啊，一些事物啊等等的一些处理，这个时候你这样的一种行为怎么来实现啊？
无无法抵御变化的这个结果肯定是不合适的。
那我们来看一下gre定义的这个设计模式啊，command设计模式怎么解决？
将请将请求封装成对象，注意啊，这里面这句话封装成对象，从而使得可以用不同的请求对客户进行参数化。
对，请你可以对请求进行排队或者记录日志，以及支持什么瑞朵安度啊。
这个就看很丰富了，就是一旦变成对象，它就有很高的灵活度了。
好，我们来看一下啊一个代码的释义的例子。
我们现在呢用一个啊这样的一个command，大家看这个类型，他塞了一个序函数▁x、▁q这样一个选啊。
然后呢所有继承自command的这些类构成的对象呢，它表达的就是一个行为对象。
那比如说我们这个下面contract，command一继承是command，然后当然你可能封装有一些啊这个请求处理过程中的一些参数信息，然后你的要偶尔的这个▁x、▁q的函数。
当然这是具体的处理逻辑。
然后比如说我们又有另外一个命令啊，counter，command二，然后这是它的处理逻辑。
好，等等这样做。
那当然我们甚至还可以用一些红命令，就是可以把多个命令组合三十八。
行，大家看这个地方其实用了类似我咱们叫那个computers的设计模式，是吧？
就是说你这个组合命令本身又继承自命令对象，然后实现这个exploit，然后通过呃遍历的方式对这个里面的组合的所有的叶子节点啊的字节点进行一个遍历操作。
好，然后当然我们封装出来了这样一些command的对象，大家看五十五行表示一个命令，对吧？
五十六行也表示一个。
命令，五十八行呢它构成加加上五十九行，那六十行构成了一个什么命令组合。
那六十二行我去执行这个，当然这只是执行了啊其实嗯这样做的它还有很多其他的啊这个好处啊，我们我们这里只是做了一个简单的组合式的命名，你一个命令可以包含多个子命令。
那么最关键这里最关键的是什么？
是从此我拿着这个command，一拿着command，r，拿着minecraft，这些都是什么对象？
但他又表征的是什么？
是行为。
呃它上面只有一个函数啊只有一个函数就是▁x、▁q，它就表征一个行。
呃大家知道你你做一个对象啊，当它表征一个行为的时候，那么你拿着这个对象，对象可以干什么？
可以当作参数来传递，可以当做这个一些字段来存储，可以做序列化啊，可以存在某些数据结构里边啊等等，对吧？
这就是说所谓灵活化啊，但它背后表征的实际上是一段代码，而且当这个代码是带有丰富的一些参数信息，表征的是这段代码。
好，我们再回到ppt来看一下啊。
嗯再来对照这句话，将请求封装为一个一个的对象。
这里边就是封装成啊一个一个的对象，这是一个对象这是一个对象，对吧？
从而使得你可以用不同的请求对客户进行参数化。
啊就是就是我们刚才说你一旦变成对象，就对象就很灵活了，对吧？
它是一个object，它是一个instance这样一个对象实例，拿着这个对象实例通常对象实例我们可以干什么？
拿着这个对象实例也可以干，但只是说它有一个特殊的含义，它是一个请求是是一个一个请求的行为。
好，我们来看一下这个类图啊，内推也比较简单啊，这个command上面这个这个是我们的抽象的接口啊，定义了命。
拟定对象的一个接口形式，然后下面呢这些可变体，这些具体的一个一个命令，那就是一些可以变化的东西，对吧？
比如说我们再举一些例子啊，那你假如实现呃比如说咱们常见的一个编辑器上的一些命令，呃呃这个嗯剪切、cat、呃、delete、test、粘贴啊、拷贝，那么这些其实都可以使体现成一些命令对象啊我当时验证命令对象之后呢，你就可以对这些对象进行一些什么。
具体来说，存储在一个一个站结构里面的一个stack结构里面，然后可以实现什么实现锐度安度操作，对吧？
就当用户做了好多不操作的时候，你可以把这些存起来，然后呢当他这个安度的时候，你又把它弹出来啊去做一些对应的安度草，这些都是这个命令对象，就是一旦把行为啊对象化之后，可能获得的好处。
好。
那当然我们这里要说的就是真正去实现，比如说你要去实现n维度n度，或者去实现这个你特殊的针对命令对象的处理逻辑，那又是另外一半业务逻辑了，对吧啊他可能很简单，可能很复杂，但是基本思想就是说要把行为封装成对象。
那么咱们这里啊最关键的就是说谈判的模式啊根本目的在于将行为的请求者和行为实现者揭露。
哦啊然后在面向对象语言中，常见的实现手段是什么？
是将行为抽象为对象，实现command接口的具体命令对象就这个contract，command有时候可以根据需要呢可能会保存一些额外的信息，就是我们刚才那个呃代码里面那个那个spring，up，对吧？
等等这些额外的状态信息。
那还有一个就是我们可以通过这个component模式呢，将多个命令封装成一个复合命令对象，这也是扛威的模式可能带来的一一一些个好处了啊，对吧？
那么嗯我们也需要说明的是command模式啊，它与这个c、g、r中间的这个函数对象，大家想一想这个是不是有有。
有学过函数对象，了解函数对象，朋友是不是由于觉得似曾相识啦，对吧？
就是都是对象，对吧？
command一是对象，command是二对象啊那么他作为一个对象，他可以执行一些行为，是吧？
嗯那么c，dr函数对象大家知道，它是利用了c。
dr的一个非常好的特征叫做什么？
可以重载那个括号调用操作符。
当然当然，另外一个就是c加函数对象。
还有一个特别好的特征呢是他跟泛性编钟结合在一起，很多时候它使用的是模板的一个叫做我们叫编译室绑定，而咱们这个地方呢对，咱们这里用的是什么执行的时候用的是运行式绑定。
比如说。
你这个▁x▁q这个▁x▁q的调用的注意都是虚函数，是吧？
你进去之后，你看这个四十五行这里是不是也是虚函数啊？
这一串虚函数的调用，那我们这里也需要说明了，有些朋友可能就会有疑问了，那command这个命令的设计模式和c加加里面的函数对象呢它是不是有一些类似啊？
对吧？
确实有一些类似啊。
而且我也要说的是，在设计模式这个定义command设计模式的时候呢，就是九四年左右，这个时间呢c加函数对象并没有广为所用啊，这家社区就泛新编程那个时候还没发展出来的，对吧？
翻译编程是什么时候啊？
是九八年左右的时候发展出来的啊，对吧？
这个时候呢之前的函数对象还是一些一些小圈子在用。
就并没有广为接受。
嗯但是后来呢大家就会发现啊，command命令模式呢和c加函数对象其实是非常类似的，现在在某些场合里面，c加加的函数对象它要优于common的模式。
那我们先来谈谈两者的区别啊，区别就是在呃两者都定义了这个就是所谓将什么将行为对象化或者将代码对象，是吧？
但两者定义行为的这个接口，它的规范是有区别的。
command模式中间的这个对象中的这个，他使用的是什么接口和实现来定义。
接口规范它更严格。
什么意思呢？
来看一下啊这个接口规范，大家看这个接口规范是什么？
函数名是▁x、k，u，返回值是word，参数是空，对吧？
这是它的接口规范啊，所以你底下继承它的这些实现这个具体command的时候，你就必须符合这个结果规范，对吧？
返回值是word啊，参数为空，名字是▁x、▁q，注意你的名字必须还是▁q▁x▁q啊。
所以呢我们说这个command他的这个接口规范的更严格，但是呢它有性能损失，就是我们刚才说的它是一个虚函数，对吧？
那是虚啊，所以它是有性能损失。
但是呢c、e、r函数对象呢它是以它是以函数签名来定义行为接口规范的，对吧？
尤其是你使用了模板之后啊。
对吧？
它只需要你的什么参数返回值一致就可以了，对吧？
名字无所谓。
嗯所以呢它在这个上面呢，我们说它更灵活，它相对于这个command设计模式呢，它在接口规范上更灵活，而且它这个接口文脉是一个隐式结构，对吧？
是有影视的，不是不是显示，而且它是要靠编译器在编译室来去去做这检检查的。
但是呢它的好处是什么？
性能更高。
为什么我们说它是一个编译室绑定啊，或者讲其实运用了这个，当然编译式绑定有些人朋友马上反应就编译式绑定是不灵活啊，对吧？
但是注意我们这里面实际上严格意义上叫做编译是多态，因为它利用了模板，如果没有模板这个这个。
函数对象其实嗯呃用处不大，对吧？
有了模板之后，函数对象的用处就非常大了。
它使用了一通编译室的模板，呃多肽技术啊就是在编译室来辨析这个函数具体调用那个函数对象。
那我们这些command设计模式，经典意义上九f定义设计模式是使用虚函数，通过运行式动态来辨析。
啊我再来看给大家看在哪里编写，比如说这里这里就是运行式动态变现你c的对象，这个实际运行时的对象是什么？
你决定你调用的函数是不一样的啊，他两个在这个方面是有一些差别的。
那么我们需要说明一下，就是基于前面的这两个区别呢，导致了啊目前呢在c加加。
它主流的这个框架里面呢，函数对象的英文更广泛，坦白来说，为什么c加加大家知道这个语言特点是什么？
性能优先，对吧？
所有在c加的所有设计选择里面，永远是性能优先的法则。
所以command设计模式呢在c加加里面的很多应用场景被什么被函数对象，就是我们讲的访函数function，object或者functionaler给替代。
但是呢这个command模式这种思想呢在其他语言里面得到了极大的这个应用，比如说像java、像say、shot、像swift这样的一些语言啊，command设计模式应用极其广泛。
所以这个模式跟咱们那个迭代器模式艾特瑞特很很很像，是吧？
就是我们说你你学了c加，在c加加里面你学这个。
伯父的艾特瑞特设计模式，你学完之后，你发现真正在c加加框架里面用用的场景真的很少啊原因是泛性编程已经把这个问题对吧性能又够更高、更灵活地迭代去实现了。
嗯那么所以你在c加加里面看到这种经典意义上g、o、f定义的迭代器模式用的很少，旁边的模式也类似，也是在c加这个这个条件下呢，泛型编程加上这个函数啊函数对象啊已经就实现了很很灵活啊、性能很高的这样一种方式。
但是呢呃我们反过来说，就是在c加当前的c加加里面，command模式和艾特瑞塔模式这些应用的没有那么广泛，并不意味着这两个模式在其他语言里面就没有用武之地啊它的整个设计思想啊这个在其他语言里面应用非常广泛，所以就是也要我们说设计模式要。
结合语言来去学习。
按照其实业界有一种观点有另外一种观点，设计模式是什么是弥补语言设计的不足而出现的。
这这个话可以啊就是有它合理的成分，对吧就是如果一个语言设计的非常非常的充沛，它的框架内裤很充沛，那可能这些设计模式呢会变成语言的face book的一部分。
呃就像函数对象，当然也有一些人把函数对象当作一种设计模式啊，也有这种说法，对吧？
但是函数对象显然已经成为c加语言的一个基本机制了，所以大家有时候就说哎那那这个情况下你就不必费费老大劲去去整一个come的设计模式了，你你使用c加的大多数情况下你使用c加函数对象就可以了。
呃好，那我们接。
今天command模式呢就给大家讲到这里。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br></div></div><h2 id="_24-访问器"><a href="#_24-访问器" class="header-anchor">#</a> 24.访问器</h2> <div class="language-txt line-numbers-mode"><pre class="language-text"><code>好，那我们开始我们cr 设计模式，visitor 啊访问器模式对讲。
那防区呢和我们前面讲的command 模式同样属于一个行为变化的模式。
我们来看一下它解决的问题。
我们接接下来对照代码来看啊。
我们说呃房期呢？
主要解决的是在软件构建过程中啊，我们有时候有一些需求的变化。
啊，会导致这个类层次结构需要添加某些新的行为。
我举一个例子，比如说我们现在这是一个类层次结构。
啊，所以有啊，这是element 是一个鸡肋，对吧？然后这底下是它的子类。
那。
比如说这是它上面已经有的一些操作函数的一些行为。
但是呢我们现在需求有变更。
哦，我们会发现我们需要添加新的行为。
那怎么做呢？对吧？大家肯定第一个直观的反应就是这样做。
加一个玩q 对吧？再加一个，比如说方可二啊，可能你再有什么参数之类的给他之类。
然后呢，在这边怎么做呢？就去override 这个方可二是吧？
啊，按这个还是带着您这个参数眼镜啊，然后在这个里边呢去做你自己的偶y 的版本的实现啊。
啊，那假设呢我们当然在这个此类里边，你其实你往往改了鸡肋。
的实现，你就要针对你所有的职能啊去提供这样的子线，是吧？
好。
那我们说这种做法呢。
可能司空见惯了，对吧？大家平时你去设计类都是这么设计的啊。
但是注意，这不是一个。
类的设计过程啊，我们讲实际上是当你已经完成了你这样一个开发。就刚才放飞疫情完成了之后。
啊，你已经部署了，已经呃呃分发了之后，你又想添加新的操作，那这个改了代价很高的，是吧？
因为嗯因为你改的是鸡肋，对吧？我们有一个前提，就是说你要在积累里边去添加针对这个对象结构的。
所有的。
纤维啊就每一个子类都要去处理这个行为。呃，o 自己的这个重写的版本。
那。
我们说这样的写法，其实大家的直观，你如果有这样一个设计模式的一个一个素养的话，你知道它是违背了我们的一个原则的，是吧？什么颜色呢？开碧源。
是吧？
这就我们不鼓励你拿着元旦在你需求变更的时候，你拿着元代码去更改。
尤其是说你这些已经开发完成，已经部署了之后。
那这个遇到这种问题怎么办？
啊，我们来看看。
啊，对着p p t 咱们再回顾一下刚才说的这个问题啊。
啊，就由于需求的变化。
好。
某些类层次结构。所以我们这里强调的是什么？是一个类层次结构。
就是从鸡肋开始，一直到你所有的子类。
都需要添加这个新的方法。
啊。
如果直接在积累中间改。
做这种更改的话，那会给此类带中带来比较繁重的变更负担。
就是你嗯你你你付了一一改，对吧？你因为是虚函数嘛，你此类肯尼亚就是说去all right 的每一个资料去为此而更改。
这个变更的负担啊，甚至有时候会破坏原有设计。
那我们讲的就是如何在不更改类层次结构，这是我我我们讲的开闭原则是什么？就不要去更改源代码。
而是实现什么？
扩展式的增加，扩展式的应对心虚新的需求变化。
所以我们这里面强调有一个运行是如何在运行时根据需要透明的。
给这个类层次结构上各个类体动态的添加新的操作。
啊。
对，当然我们刚才讲的是什么？是。
你这种方式不灵活，对吧？因为你这样讲，那过一段时间用户又需要讲，又需要再加新的呢。在家放个三呢。
在家放合适呢，对吧？等等这样的需求变更。那你这个这个方式就招架不住了，对吧？
那我们visa 模式我们来看一下它是怎么样解决这个问题的。
我们来了。
那另外一段代码。
v 人才是这样子，就是说。
首先问一下，有一个前提啊，我能预料到未来可能会更添加为这个整个类层次结构添加新的操作。
我能有这样一个预预预料啊。
啊，但是我不知道要加多少操作，我不知道具体家的是什么操作。
啊，就是我现在没法定是吧，没办法定。比如说那如果当然我现在能定下来加五个操作，我当初就把它设计好。
还是说我在我完成之后，我未来要增加多少个操作，要增加什么样的操作，我是不知道的。
好，那这个时候呢你就需要做一个预先的设计。
就是我们这里面这个visa 由我设计一个accept 这样一个对accept 是一个虚函数。
然后再放一个visitor 的泪。
wait 类呢在下面。
在这里。
那大家先扫一眼啊，我马上再解释维特尔类里面针对每一个子类去写一个欧这个虚函数。
we visited them, if even that it be. 
然后eleven a 呢？
继承子。
i element 这样一个鸡肋啊，然后去重写这个accept 这个函数。
当重写这个accept 函数的时候呢。
在里边怎么调用，对于他接受一个参数叫vg t 啊，对吧？那我们拿着这个vg 才去调用visitor a elma。
对呀，其实就是这个选三十七号这个学员。
然后a l m 的b 去继承这个element 的话，就是也是去重写这个accept 函数一样的啊visitor。
点visit is eleven a b 就是调用三十八行这个血案。
啊。
嗯，然后当然这个面传的是什么？this 当前的对象传的是aim 的a 你visa ma 的是吧？就创业mma，which is it? mb 的话就穿a b。
好，那这样的一个写法里边啊。
嗯，解决了什么问题？其实目前只是什么预先的设计了，我将来可能会增加新的操作。
好，那。
如果我将来啊我们先画一条线。
这条线。
这条线之上是我现在已经做好我的设计了。好。
这条线呢之下就是将来啊就是这样。那么我现在有新的需求了，对吧？我需要给前面的整个类层次结构添加新的操作，怎么做呢？
我就继承一个visitor 的子类。
在这个子类里边呢。
大家看我们是怎么做的。
我们去实现这个。
visit element, the a 和visit element d 这样一个虚函数。
嗯，然后分别去针对a m 的a 操作，针对他们的b 进行操作。
啊。
好，其实就是。
所谓添加我的操作。
对吧，添加我的操作，然后呢。
再来看这个。
如果我在将来又有新的其他的需求，比如我再加一种处理visitor 二。
然后我去继承这个vit 一样的，我也是去偶尔外的这个vita and ma v and mb 这样一个版本。
好，那么在达到一个什么效果啊？
所以啊这个地方需要大家瞪大眼睛看啊。
visiter, 假如说我现在需要给。
啊，这个添加这个visa 二的这一组操作。
那我是这样做，我先创建一个v 二的这样一个对象。
然后再创建一个，比如说element b 这样一个对象。
啊，那我需要给m 的b 添加操作呢，我就直接这样调用element d accept，visit. 
注意啊，再看这这这这个调用，这个调用是咱们维萨模式里面最重要的。大家要理解这个。
首先呢你看a elm 的点accept 找谁调用了。
因为mx 的实际类型注意它是个虚函数，对吧？
那么accept 是个虚函数，就要找a eleven。
的呃真实的运行时类型运势类型是什么？是ai m 的b 是吧？
那好。
在哪里呢？
就在这里对吧，是不是跑到这个函数上？
对呀，就是跑到现在第一个调用分发到二十八行。
这是一个多态调用，对吧？
还是八行调用进来之后，二十九行注意看啊。visitor 点with element b 这个vitter 是谁呢？我们传了一个参数。
传的是一个vista 二，对不对？
那就进来，这是维斯特二，现在它实际类型。
它的运行是类型是visit 二。
所以我们是传引用啊多态的对象，信息就传过来了。
然后反问vita eleven 的b。
那。
wait 是不是有一个。
啊，这个虚函数叫vista 的b。
那么现在就要找这个威特的实际类型，有运行时类型是什么？visa 二是不是是跑到这里了？
对不对？
就去执行这个选函数呃，偶尔尔d 的版本。那直线的结果就是这样。
当然。
也就是也就是我们想给v。
想给他们的d。
添加的啊vit 二的一种操作。
就是动态的添加操作进来了，对吧？当然你这里边也仍然可以写，比如说a element a。
嗯。
在南门。
假如这个。
a 吧啊让我这个上面就写着嗯。
厉害。
啊，这边就是b。
那a w ma 那我就去调用呢，a m 起来。
a 点accept。
把我传递这个with。
第七十六行大家再来看啊，第七十六行最终是调，我们现在可以直接说结论啊，最终调用的结果是五十八行，但它调用过程是怎么样的呢？
先去找a elma 的accept。
在哪里，这里是吧？
然后好这一次动态辨析。
然后进来之后十九行。
啊。
又是一个v orv 特是什么？我们的vista 二是吧？那就又跑到这里。
调用的是哪个函数呢？
胃疼。
a 咱们a 这个函数。
那就是五十七行，这个很。
好，那结果是什么？就是这个是吧？
嗯。
因为我们传递是vista r 针对m 的a 的一种访问。
所以这里啊大家来看我们这个维权模式里边有。
有一个叫做我们叫做double dispatch。
double this set. 
w w distance 叫二次分二次。变形多态辨析啊，这个dispatch 是多态辨析的意思。
哪两次呢？我们先来看啊，第一次是在那什么在调用accept 这个虚函数的时候。
对吧，就在这里，第一次是在调用这个。
这时候第一次。
多态。
变现或者叫动态变形。
对吧，那么当然要找他的子类是吧，我们刚才比如说如果是a elm 的b 的话，那就找到的是这个子类的实现o r y 的版本。
还有一个第二次动态。鞭溪是什么？是根据这里边这又是一个虚函数是吧？visitor 点vit mb。
啊，这是第二次动态练习。
啊。
这有两次动态变形啊，当然你如果访问的a m 的a 那就在这里面都多。第二次动态辨析啊，这是唯一摄影模式里面。
非常重要的一个细节。
啊，呃非常著名的一个说法啊，叫做双呃两次派遣两样或者两次变细。
好，我们回到p p t 啊来看一下。
later 模式啊。
表示一个作用于某对象结构的各个元素的操作。
对象结构，这个我们这里说的对象结构指的是谁呀？
就是咱们这个a mx 鸡肋，a m a a m 的b 这构成了一个对象结构。当然我们演示的情况，我们只设计了。
他们的只有两个之类，对吧？但实际的情况可能啊你这个a elm 的有有非常多的脂类，对吧？比如你有十个子类。
这个使得可以在不改变各个元素的类的前提下。
注意看这个绿线条啊，绿线条以上的是我们不会去改变的。
感觉这些这这些类层次结构已经设计好了，他们相关的函数已经设计好了。
啊，我们是不改变他们的。
就是这个这个改变是指的是编译时啊，编译是源代码层次面的改变，对吧？我们不改变各个元素的类的。
呃，前提下去定义作用于这些啊元素的新的操作。
所以这个这个解读啊，这个定义实际上是一个扩展的方式。
啊。
这这就是新的操作。比如我要给a l m te 啊这个a b 添加一种新操作，是这样子。
啊，如说我再添加另外一种新操作，是这样子。
啊，每一次在添加。
添加一次新操作都是什么扩展？
都是扩展啊，这就是开闭原则的体现，对吧？
扩展就是我用子类的方式啊啊实现了这样的一个新的操作。
那好，那我现在的问题是啊，我们来对照这幅图啊，咱们先来看一下这幅图。
visiter. 
对应呢咱们呢以这个waiter 这里，对吧？
啊，看清楚了啊。
我我估计有些朋友可能刚才解读代码过程中，反过来还是有一些朦朦胧胧，有一些细节不理解。现在我们是来解释一下啊，对要图再来解释。
witter 在这里，然后那个vz 一在哪里在这里？
对吧？concrete visitor 一。
康奎的visit 二在哪里，在这里？
啊。
然后那个a eleven 在哪里？
是我们的鸡肋，对吧？
然后a eleven a 在哪，在这里？
给咱们的b 在这里。
啊，要注意里面的accept 函数非常重要。啊，吓不住啊，在这里。
好，大家现在已经能和我们的代码对应起来了，这个类的结构我们现在要做的事情是什么？我来画图。
我们来钩画一下这幅图里面的几个关键点，需要大家来理解。
那我们现在说这个设计模式，它上去很多人会有一个感受，就是觉得哎。
他有些缺点是吧？
那我们来看一下它的缺点是什么。他有一个非常大的缺点，这个模式不是随便就能用的啊，它的缺点是。
啊，我们还是用我们之前的观点，就是画红红色啊，红颜色。我把这个这个模式要求的稳定的部分定义下来。
哪些是这个模式有稳定的？
这个部分首先来看啊，这个visit 要稳定。
那这个it element 要稳定。
啊。
但是这两个稳定是不够的啊。
因为visa 稳定。注意看啊微博里面需要什么，需要concrete it mma 需要concrete a mb 实际上呢也要求这类稳定。
这是这个模式非常重要的一点。
很多人会忽视这一点，就。
当你忽视姐，你这个模式就学不明白了。
can create it. 他们的a concrete，a m, d. 
都必须是稳定的。
为什么？
因为你这里边这个visitor，当你写videt 的时候，你必须知道eleven 有几个此类。
他有五个子类，那你就有五个。visit it 的conquete a m 的await country teammate bv 的country 的给他们的c 等等这样的函数，对吧？
所以vit 这个类啊要写下来的前提是这个element 类的子类能够什么。
个数能够确定。
哇，这是一个非常大的前提啊，这个前提很容易保证不到，对吧？
大家想一下。
呃，你比如。
我有一个面向对象，假如我要设计一个图形系统，这个图形系统它有shift 鸡肋，有react，通过子类啊，有有circle 之类，又烂之类等。
这些之类。
但这个设计模式要求这些子类必须稳定，就要求这些子类必须确定下来，而这个条件常常满足不了。
对啊，常常满足不了。
为什么？就是说如果你不没满足这个这个条件啊，大家想要会出现什么情况？
我现在假如我这个a i went 新加一个新的子类。
比如说adem the say。
那这个visiter 是不是要跟着改变啊？
啊，这个waiter 的鸡肋就要跟着改变。
那就为其实违背了这个模式的一个前提假定条件。
那你就要又又又打破了开闭原则，你又得回去更改这个v 的这样一个一个类的实现是吧？当你更改这个wait 类的实现的时候。
那么你这个相应的依赖关系自己重新编译是吧？
所以呢。
这里边就是visa 的鸡肋的稳定的前提是a elm 的所有子类都确定。
这是这个模式非常大的一个缺点。
啊。
那我们也需要说一下就是。
这里边我用蓝色来划，那哪哪个部分是。
是可以变化的呢是扩展式的变化。
所以我来画蓝色的。
在这里。
那就将来我需要添加新的操作的时候，我就去继承vit 实现维权的一个新的子类。
比如说waiter 三是吧，然后针对它里面的所有的函数，它是它里面都哪些内涵？路干什么啊？
就是我们讲的v 在aim 的a，this is eleven dvc 等等，对吧？是针对aim 的整个类层次结构的一个。
所有的防护方法。
简单来说，你element 有几个子类？
比如有十个子类，那么你wait 就得有十个方法。
对吧，这就是这个模式里边啊，他要求他的稳定的部分。
坦白来说。
这个模式啊，它要求这个稳定就带来他的极大的一个一个一个一个脆弱性。
因为我们所以有很多时候呢是不稳定。那当然有朋友就会停俩，是如果这个a elm 类层次结构不能稳定。
那怎么办呢？
真的没办法啊，威特这个模式就不适用了。
注意啊，这个前提讲条件啊，a element 这个类层次结构如果稳定不下来，就是你的此类个数定不下来。那么你整个这个vat 模式是。
没有意义的这样写什么样的？
呃，他存在的前提条件是a event 的这个。
类层次结构啊之类必须稳定。所以这个这个模式条件极其苛刻，对吗？非常苛刻啊，因为就是我们说这个条件不容易达成。
啊，不容易满足。
啊，非常苛刻。
啊。
好，那。
咱们再回到啊回到我们这个下一页p p t 里面来看一下啊，这个咱们再总结一下。
这是。
later 模式通过所谓的双重分发。
double dispatch. 
来实现在不更改。
a element 类层次结构的前提下。
对吧就是什么叫不更改啊，我们的第一种对吧？我们刚才的这个就不更改啊，就是说你不要在a m 点上直接去。
添加新的源代码，添加新的函数。
在运行时，透明的为类层次结构的各个类动态的添加新的操作。
啊。
对吧，那么新的操作就是这些啊在这个这个这个线条之下。
这都是属于这是第一组性的操作。第二组新的操作。
对吧，上面必须是稳定的。
上面必须是稳定的。
这个我不改变你对吧？我不改变这个绿色线条以上的。
但是这有一个前提。
你写这个函数是为了什么？是为了为就是相当于为将来做做一个伏笔。
啊，就是将来需要添加新的操作，就找什么找accept。
是。
那就是围着他这个模式。
那我们来解释一下它的双重分发。double dispatch 是在哪里呀？
刚才解释过再来看一遍啊，这个模式比较绕啊。
在这里第一第一个是调用accept 函数的时候。
因为你是个虚函数，所以找你的。
子类的over yr 的版本实现。比如说找到这里要用这个二十八行，二十八号进来之后。
visitor dv tera 的b。
这个时候。
又是一次渲染树，对吧？那么这个虚函数呢？
啊，我们再来看我们传的参数是什么呢？是a w m 的二是吧？这也行啊，这样穿的a m 的二，那a l m 的二上去调用。
这个vita m 的b 是吧，那么就又找到什么，找到v 他的实现啊之类啊，就是在这里。
是吧就出来就是六十四行的这句话。
啊。
呃，刚才这里就进行了第二次的虚函数的动态变稀或者叫多态变形啊，这个就是double dispatch。
啊。
这个这个这个是维特尔模式里面非常著名的一个东西啊。
叫双重分发。
然后呢waiter 模式的缺点呢。
再来说一下它的缺点啊，我们刚才其实也知道了啊。
呃，就是他的整个这个。
类层次结构。
就是以a element 为啊为鸡肋的这些所有的子类这个类层次结构必须。
在写v 材的时候能够确定下来。
啊，如果你改变的话，这个vt 模式就不存在了啊，就不能稳定下来了，是吧？
嗯。
就是如果你扩展这个类层次结构，比如说哎我过段时间又改改了门的，加一个新的子类怎么办呢？那winter 类是不是就要又要。
要改变怎么改啊，你这里面是不是要加薪的？现在比如说vit 特element 的ca 这样的函数。
这个就其实已经违背了wait 模式的一个基础了。
因此呢大家注意看重点看这句话啊，最后一句话非常重要。
因此我们讲waiter 模式适用于什么？
a 人们乘类层次结构稳定。
就是你这个鸡肋有多少个子类是确定的，不会再增加新的子类了。
但是其中的操作却经常面临频繁改动。
这就就又是我们讲的设计模式的最大的艺术的地方在哪里啊，有稳定的地方，有变化的。
对吧？a element 类的层次结构是稳定的。
而他的操作却需要频繁的变化，就是哎过一段是先想讲给这个所有的子类加这样一个操作，过一段时间又想给梓乐加那样一种操作。
啊，这这这个不能稳定下来，你要经如果能稳定下来是吗？那也没有必要用用v 层模式了，是吧？能够稳定下来。你当初你就。
在im 里面把这些操作，比如说你十个函数你都写好不就完了吗？你干嘛要绕兜这么大一个圈子了？
对吧？
所以大家又回到我们说谁摄影模式最大的艺术在于哪里啊，就是稳定点，变化点。
谁稳定，谁变化一定要分得清楚啊，这个分不清楚，很多东西就没有没有一个。
大家看这个这个部分是稳定的啦，a 他们的类的层次结构是稳定的，但其中的操作却经常变动。
我们现在假设了两种情况，一种情况是a m 的类的层次结构是不稳定的。
那怎么办？那vs 模式就没有用了，就就就就没法写，对吧啊？
因因为你这样会会破坏他的这个这个前提啊。那另外一种假设是，如果其中的操作不需要频繁改动。
对我已经是确定的。那么用这个来mv 特尔设计模式没啥用，对吧？
就是。
简单来说，设计模式。
咱们在学习设计模式中，你不能假定两种极端情况，一种极端情况是什么？所有东西都稳定。
那用这个设计模式。
啊，没啥用处，你就不需要用这个设计模式啊。
第二种情况是，假设这个所有地方都在变化。
啊，那我们说啊你任何模式都解决不了你的问题。
对吧我们的常态是什么？是里边有稳定的部分，有变化的部分啊，所以就是咱们讲的设计模式的要点是什么？是要。
能够判断出来其中的稳定点和变化的。如果你这个判断出错了，那你后边的时候设计模式再去搞的哈，他他就是错的。
对吧？
好，later 这个模式啊比较复杂啊，理解起来啊，刚开始理解起来，其实有一天。
啊，这个思维弯弯绕的一些难度啊，大家要去反复，一定要抓住我讲课里面的几个这个重重点啊，然后分清楚哪些变化的，哪些稳定的，然后。
着代码来思考，你就会理解韦斯特这个模式的精髓啊，但是我们也是说也因此啊waiter 模式是什么，一般不用啊，他用的很少。
就是他那个前提条件太严格了，对吧？太苛刻了啊。
但是一旦用就用的特别重。
对吧，所以特别重，就是花你整个类层次结构都要被微厕所所所绑架，是吧？
啊，说左右。
所以我们说这个模式啊用了用的很少啊，现实中你看的很少，但是一旦用的话啊，这个这个就用的非常非常重。
好，那我们今天这个waiter 模式呢，我们就讲到这里。

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br><span class="line-number">123</span><br><span class="line-number">124</span><br><span class="line-number">125</span><br><span class="line-number">126</span><br><span class="line-number">127</span><br><span class="line-number">128</span><br><span class="line-number">129</span><br><span class="line-number">130</span><br><span class="line-number">131</span><br><span class="line-number">132</span><br><span class="line-number">133</span><br><span class="line-number">134</span><br><span class="line-number">135</span><br><span class="line-number">136</span><br><span class="line-number">137</span><br><span class="line-number">138</span><br><span class="line-number">139</span><br><span class="line-number">140</span><br><span class="line-number">141</span><br><span class="line-number">142</span><br><span class="line-number">143</span><br><span class="line-number">144</span><br><span class="line-number">145</span><br><span class="line-number">146</span><br><span class="line-number">147</span><br><span class="line-number">148</span><br><span class="line-number">149</span><br><span class="line-number">150</span><br><span class="line-number">151</span><br><span class="line-number">152</span><br><span class="line-number">153</span><br><span class="line-number">154</span><br><span class="line-number">155</span><br><span class="line-number">156</span><br><span class="line-number">157</span><br><span class="line-number">158</span><br><span class="line-number">159</span><br><span class="line-number">160</span><br><span class="line-number">161</span><br><span class="line-number">162</span><br><span class="line-number">163</span><br><span class="line-number">164</span><br><span class="line-number">165</span><br><span class="line-number">166</span><br><span class="line-number">167</span><br><span class="line-number">168</span><br><span class="line-number">169</span><br><span class="line-number">170</span><br><span class="line-number">171</span><br><span class="line-number">172</span><br><span class="line-number">173</span><br><span class="line-number">174</span><br><span class="line-number">175</span><br><span class="line-number">176</span><br><span class="line-number">177</span><br><span class="line-number">178</span><br><span class="line-number">179</span><br><span class="line-number">180</span><br><span class="line-number">181</span><br><span class="line-number">182</span><br><span class="line-number">183</span><br><span class="line-number">184</span><br><span class="line-number">185</span><br><span class="line-number">186</span><br><span class="line-number">187</span><br><span class="line-number">188</span><br><span class="line-number">189</span><br><span class="line-number">190</span><br><span class="line-number">191</span><br><span class="line-number">192</span><br><span class="line-number">193</span><br><span class="line-number">194</span><br><span class="line-number">195</span><br><span class="line-number">196</span><br><span class="line-number">197</span><br><span class="line-number">198</span><br><span class="line-number">199</span><br><span class="line-number">200</span><br><span class="line-number">201</span><br><span class="line-number">202</span><br><span class="line-number">203</span><br><span class="line-number">204</span><br><span class="line-number">205</span><br><span class="line-number">206</span><br><span class="line-number">207</span><br><span class="line-number">208</span><br><span class="line-number">209</span><br><span class="line-number">210</span><br><span class="line-number">211</span><br><span class="line-number">212</span><br><span class="line-number">213</span><br><span class="line-number">214</span><br><span class="line-number">215</span><br><span class="line-number">216</span><br><span class="line-number">217</span><br><span class="line-number">218</span><br><span class="line-number">219</span><br><span class="line-number">220</span><br><span class="line-number">221</span><br><span class="line-number">222</span><br><span class="line-number">223</span><br><span class="line-number">224</span><br><span class="line-number">225</span><br><span class="line-number">226</span><br><span class="line-number">227</span><br><span class="line-number">228</span><br><span class="line-number">229</span><br><span class="line-number">230</span><br><span class="line-number">231</span><br><span class="line-number">232</span><br><span class="line-number">233</span><br><span class="line-number">234</span><br><span class="line-number">235</span><br><span class="line-number">236</span><br><span class="line-number">237</span><br><span class="line-number">238</span><br><span class="line-number">239</span><br><span class="line-number">240</span><br><span class="line-number">241</span><br><span class="line-number">242</span><br><span class="line-number">243</span><br><span class="line-number">244</span><br><span class="line-number">245</span><br><span class="line-number">246</span><br><span class="line-number">247</span><br><span class="line-number">248</span><br><span class="line-number">249</span><br><span class="line-number">250</span><br><span class="line-number">251</span><br><span class="line-number">252</span><br><span class="line-number">253</span><br><span class="line-number">254</span><br><span class="line-number">255</span><br><span class="line-number">256</span><br><span class="line-number">257</span><br><span class="line-number">258</span><br><span class="line-number">259</span><br><span class="line-number">260</span><br><span class="line-number">261</span><br><span class="line-number">262</span><br><span class="line-number">263</span><br><span class="line-number">264</span><br><span class="line-number">265</span><br><span class="line-number">266</span><br><span class="line-number">267</span><br><span class="line-number">268</span><br><span class="line-number">269</span><br><span class="line-number">270</span><br><span class="line-number">271</span><br><span class="line-number">272</span><br><span class="line-number">273</span><br><span class="line-number">274</span><br><span class="line-number">275</span><br><span class="line-number">276</span><br><span class="line-number">277</span><br><span class="line-number">278</span><br><span class="line-number">279</span><br><span class="line-number">280</span><br><span class="line-number">281</span><br><span class="line-number">282</span><br><span class="line-number">283</span><br><span class="line-number">284</span><br><span class="line-number">285</span><br><span class="line-number">286</span><br><span class="line-number">287</span><br><span class="line-number">288</span><br><span class="line-number">289</span><br><span class="line-number">290</span><br><span class="line-number">291</span><br><span class="line-number">292</span><br><span class="line-number">293</span><br><span class="line-number">294</span><br><span class="line-number">295</span><br><span class="line-number">296</span><br><span class="line-number">297</span><br><span class="line-number">298</span><br><span class="line-number">299</span><br><span class="line-number">300</span><br><span class="line-number">301</span><br><span class="line-number">302</span><br><span class="line-number">303</span><br><span class="line-number">304</span><br><span class="line-number">305</span><br><span class="line-number">306</span><br><span class="line-number">307</span><br><span class="line-number">308</span><br><span class="line-number">309</span><br><span class="line-number">310</span><br><span class="line-number">311</span><br><span class="line-number">312</span><br><span class="line-number">313</span><br><span class="line-number">314</span><br><span class="line-number">315</span><br><span class="line-number">316</span><br><span class="line-number">317</span><br><span class="line-number">318</span><br><span class="line-number">319</span><br><span class="line-number">320</span><br><span class="line-number">321</span><br><span class="line-number">322</span><br><span class="line-number">323</span><br><span class="line-number">324</span><br><span class="line-number">325</span><br><span class="line-number">326</span><br><span class="line-number">327</span><br><span class="line-number">328</span><br><span class="line-number">329</span><br><span class="line-number">330</span><br><span class="line-number">331</span><br><span class="line-number">332</span><br><span class="line-number">333</span><br><span class="line-number">334</span><br><span class="line-number">335</span><br><span class="line-number">336</span><br><span class="line-number">337</span><br><span class="line-number">338</span><br><span class="line-number">339</span><br><span class="line-number">340</span><br><span class="line-number">341</span><br><span class="line-number">342</span><br><span class="line-number">343</span><br><span class="line-number">344</span><br><span class="line-number">345</span><br><span class="line-number">346</span><br><span class="line-number">347</span><br><span class="line-number">348</span><br><span class="line-number">349</span><br><span class="line-number">350</span><br><span class="line-number">351</span><br><span class="line-number">352</span><br><span class="line-number">353</span><br><span class="line-number">354</span><br><span class="line-number">355</span><br><span class="line-number">356</span><br><span class="line-number">357</span><br><span class="line-number">358</span><br><span class="line-number">359</span><br></div></div><h2 id="_25-解析器"><a href="#_25-解析器" class="header-anchor">#</a> 25.解析器</h2> <h2 id="_26-设计模式总结"><a href="#_26-设计模式总结" class="header-anchor">#</a> 26.设计模式总结</h2> <h3 id="_26-1-一个目标"><a href="#_26-1-一个目标" class="header-anchor">#</a> 26.1.一个目标</h3> <ul><li>『PPT』：管理变化、提高复用！</li></ul> <h3 id="_26-2-两种手段"><a href="#_26-2-两种手段" class="header-anchor">#</a> 26.2.两种手段</h3> <ul><li>分解VS.抽象</li></ul> <h3 id="_26-3-八大原则"><a href="#_26-3-八大原则" class="header-anchor">#</a> 26.3.八大原则</h3> <ul><li>依赖倒置原则(DIP )</li> <li>开放封闭原则( OCP)</li> <li>单一职责原则(SRP )</li> <li>Liskov替换原则(LSP )</li> <li>接口隔离原则(ISP )</li> <li>对象组合优于类继承</li> <li>封装变化点</li> <li>面向接口编程</li></ul> <h3 id="_26-4-重构技法"><a href="#_26-4-重构技法" class="header-anchor">#</a> 26.4.重构技法</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210806164214606.png" alt="image-20210806164214606"></p> <h3 id="_26-5-从封装变化角度对模式分类"><a href="#_26-5-从封装变化角度对模式分类" class="header-anchor">#</a> 26.5.从封装变化角度对模式分类</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210806164310449.png" alt="image-20210806164310449"></p> <h3 id="_26-6-c-对象模型"><a href="#_26-6-c-对象模型" class="header-anchor">#</a> 26.6.C++对象模型</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210806164432262.png" alt="image-20210806164432262"></p> <ul><li>变化点和稳定点</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210806164452760.png" alt="image-20210806164452760"></p> <h3 id="_26-7-什么时候不用模式？"><a href="#_26-7-什么时候不用模式？" class="header-anchor">#</a> 26.7.什么时候不用模式？</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210806164528396.png" alt="image-20210806164528396"></p> <ul><li>经验之谈</li></ul> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210806164601888.png" alt="image-20210806164601888"></p> <h3 id="_26-8-设计模式成长之路"><a href="#_26-8-设计模式成长之路" class="header-anchor">#</a> 26.8.设计模式成长之路</h3> <p><img src="https://cdn.jsdelivr.net/gh/HACV/picture/img/image-20210806164634246.png" alt="image-20210806164634246"></p></div> <div class="page-edit"><!----> <!----></div> <!----> </div> <!----></div></div>
    <script src="/assets/js/app.c70e21ad.js" defer></script><script src="/assets/js/89.17c69819.js" defer></script>
  </body>
</html>
